younginnovations / iatipublisher

IATI Publishing Tool
GNU Affero General Public License v3.0
7 stars 0 forks source link

Translation workflow and documentation #1279

Open PG-Momik opened 1 year ago

PG-Momik commented 1 year ago

📖 Context:

🔵 1 : The basics

📑 en/source_1.php

returrn [
    'hello_label' => 'Hello!',
    'hello_description' => 'Hello, I hope you have a lovely day today',
    'hello_username_with_mail' => 'Hello :username, you've got mail.'
];

📑 es/source_1.php

return [
    'hello_label' => '¡Hola!',
    'hello_description' => 'Hola, espero que tengas un hermoso día hoy.',
    'hello_username_with_mail' => '¡Hola :username, tienes correo!'
];

📑 fr/source_1.php

return [
    'hello_label' => 'Bonjour !',
    'hello_description' => 'Bonjour, j'espère que vous passerez une belle journée aujourd'hui.',
    'hello_username_with_mail' => 'Bonjour :username, vous avez du courrier.'
];

🔵 2 : Usage

We can now show translated text in an app using the complete key of said text.

EN FR ES
Hello Bonjour ! ¡Hola!
Hello, I hope you have a lovely day today Bonjour, j'espère que vous passerez une belle journée aujourd'hui. Hola, espero que tengas un hermoso día hoy.
EN FR ES
Hello Sam, you've got mail. Bonjour Sam, vous avez du courrier. ¡Hola Sam, tienes correo!

📖 Implementation

🔵 1 : Overview

To modify the app's language, we use setLocale() method provided by Laravel. When the user selects a language option, a request is sent. The request contains the selected language which is used by the setLocale() method.

Untitled-2023-06-21-0825

1.1 : Folder structure

The directory containing all the language files i.e. lang directory can be found in root directory itself. All the translation file are group based on the language. We've maintained the files in the folders as follows:

root / lang
      |
      |---en
      |       |-- about.php
      |       |-- activities.php
      |       |-- activity_default.php
      |       |-- activity_detail.php
      |       |-- buttons.php
      |       |-- common.php
      |       |-- elements.php
      |       |-- elements_common.php
      |       |-- ........etc
      |
      |
      |--- es
      |       |-- about.php
      |       |-- activities.php
      |       |-- activity_default.php
      |       |-- activity_detail.php
      |       |-- buttons.php
      |       |-- common.php
      |       |-- elements.php
      |       |-- elements_common.php
      |       |-- ........etc
      |
      |
      |--- fr
      |       |-- about.php
      |       |-- activities.php
      |       |-- activity_default.php
      |       |-- activity_detail.php
      |       |-- buttons.php
      |       |-- common.php
      |       |-- elements.php
      |       |-- elements_common.php
      |       |-- ........etc

1.2 : Working mechanism

Scenario 1 : Translating simple/complete text :
Desired text : "IATI Publisher helps small and medium-sized organisations publish IATI data on development and humanitarian financing and activities"

Scenario 2 : Translating dynamic text with placeholders : Desired text : "Default-tied status updated successfully"

translateJsonValues()

This function translate translatable values in a json object. This function is only called when forms need to be rendered. Read 2.2 Translation for JsonSchemas for more info.

translateRequestMessage()
translateRequestMessage('the_sum_of_recipient_regions_and_recipient_country')  
translateRequestMessage('narrative_language', 'must_be_unique')  
translateRequestMessage('the_budget_period', 'must_not_be_longer_than_1_year')  
EN FR ES
The sum of percentages of Recipient Region(s) and Recipient country must be 100% La somme des pourcentages des régions bénéficiaires et du pays bénéficiaire doit être de 100 % La suma de los porcentajes de la región o regiones receptoras y el país receptor debe ser igual a 100.
The Narrative language must be unique. La langue de l’exposé doit être unique. El idioma de la descripción debe ser un único.
The Budget Period must not be longer than one year. La Période Budgétaire ne doit pas durer plus d’un an. El Período del Presupuesto no debe exceder un año.
getLabelForAddAdditional()
getLabelForAddAdditional('title')  
getLabelForAddAdditional('type')  
getLabelForAddAdditional('narrative')  
EN FR ES
Add additional title Ajouter titre Añadir título
Add additional type Ajouter type Añadir tipo
Add additional narrative Ajouter exposé Añadir descripción
translatedElement()
translatedElement('activities.title')  
translatedElement('activities.recipient_region')  
translatedElement('activities.narrative')  
EN FR ES
title titre título
recipient region région bénéficiaire región receptora
narrative exposé descripción
translateResponses()
translateResponses('mismatch_csv_header')  
translateResponses('please_upload_csc_or_xml')  
translateResponses('make_sure_publisher_is_approved')  
EN ES FR
Mismatch csv header Encabezado CSV no coincide En-tête CSV non correspondant
Please upload csv or xml file to import activity. Suba el archivo CSV o XML para importar la actividad. Téléchargez un fichier CSV ou XML pour importer l’activité.
Please make sure that your publisher is approved in IATI Registry. Asegúrese de que su entidad está aprobada en el Registro de la IATI. Assurez-vous que votre signataire est approuvé dans le registre de l’IITA. - translateElementSuccessfully()
translateElementFailed()
translateElementFailed('activity', 'delete')  
translateElementFailed('elements_common.activities', 'validation')  
EN FR ES
Activity delete failed. Échec activité supprimer. Fallo en eliminar actividad.
Activities validation failed. Échec activités validation. Fallo en validación actividades.
translateErrorHasOccurred()
translateErrorHasOccurred('responses.the_data', 'fetching')  
translateErrorHasOccurred('elements_common.period', 'rendering', 'form')  
translateErrorHasOccurred('responses.result_detail', 'rendering', 'page')  
EN FR ES
Error has occurred while fetching the data. Erreur sur recherche les données. Se ha producido un error buscando los datos.
Error has occurred while rendering period form. Erreur sur le formulaire interprétation période. Se ha producido un error representando formulario de período.
Error has occurred while rendering result detail page. Erreur sur la page interprétation informations sur le résultat. Se ha producido un error representando página de detalles del resultado.
translateElementDeleteError()
translateElementDeleteError('elements_common.indicator')  
translateElementDeleteError('elements_common.period')  
EN FR ES
Indicator Delete Error. Erreur De Suppression Indicateur. Indicador Borrar Error.
Period Delete Error. Erreur De Suppression Période. Período Borrar Error.
translateCommonError()
translateCommonError('this_activity_has_been_duplicated')  
translateCommonError('element_already_exists_in_iati_registry', 'common.iati_organisational_identifier')  
translateCommonError('elements_doesnt_match_iati_registry', 'register.publisher_id.label')  
EN FR ES
This Activity has been duplicated in the uploaded Csv File. Cette activité a été dupliquée dans le fichier CSV téléversé. Se ha duplicado esta actividad en el archivo CSV cargado.
IATI Organisational Identifier already exists in IATI Registry. Identifiant de l’organisation de l’IITA existe déjà dans le registre de l’IITA. Identificador de organización de la IATI ya existe en el Registro de la IATI.
Publisher ID doesn't match your IATI Registry information. Identifiant du signataire ne correspond pas aux informations du registre de l’IITA. Identificador de entidad que publica no coincide con su información en el Registro de la IATI.
translateButton()
translateButton('save_and_exit')  
translateButton('cancel')  
EN FR ES
Save and Exit Sauvegarder et quitter Guardar y salir
Cancel Annuler Cancelar
translateDoesntExist()
translateDoesntExist('common.activity')  
translateDoesntExist('common.period')  
EN FR ES
Activity does not exist. Activité n’existe pas. Actividad no existe.
Period does not exist. Période n’existe pas. Período no existe.
translateCommon()
translateCommon('another_bulk_publish_in_progress')  
translateCommon('placeholder.select_a_value')  
translateCommonError('you_have_not_verified_your_email')  
EN FR ES
Another Bulk publish in progress Autre publication groupée en cours Otra publicación masiva está en curso
Select a value Sélectionnez une valeur Seleccionar un valor
You have not verified your email address. Vous n’avez pas vérifié votre adresse e-mail. No ha verificado su dirección de correo electrónico.

1.2.2 : Front-end Function

The helper function for the frontend can be found in translationHelper.ts. Similar to the backend helper functions, the front end helper function also uses keys of the language files as the source.

Note : All the functions are methods of the Translate class.

button()
translate.button('publish')  
translate.button('add_element', 'common.new_result')  
translate.button('not_yet_added_period')  
EN FR ES
Publish Publier Publicar
Add new result Ajouter nouveau résultat Añadir nuevo resultado
You haven't added any period yet. Vous n’avez pas encore saisi de période. No ha añadido ningún período aún.
event()
translate.event('deleting')  
translate.event('published')  
translate.event('unpublishing')  
EN FR ES
deleting suppression eliminando
published publié publicado
unpublishing annulation de la publication cancelando publicación
element()
translate.element('results')  
translate.element('language')  
translate.element('type_narrative_here')  
EN FR ES
results résultat resultado
language langue idioma
Type narrative here Saisir exposé ici Introducir descripción aquí
error()
translate.error('activity_could_not_be_published')  
translate.error('some_activities_have_failed_to_publish')  
EN FR ES
Activity couldn't be published because : L’activité n’a pas pu être publiée pour le motif suivant : No se pudo publicar la actividad por el siguiente motivo:
Some activities have failed to publish. Certaines activités n’ont pas pu être publiées. Ha fallado la publicación de algunas actividades.
commonText()
translate.commonText('the_iati_standard_contains_wide')  
translate.commonText('publishing_progress')  
translateCommonError('element_already_exists_in_iati_registry', 'user.user_name')
EN FR ES
The IATI Standard contains a wide range of data elements and your organisation is encouraged to (at least) publish data in elements marked as “Core”. La norme de l’IITA englobe divers éléments de données et votre organisation est encouragée à publier (au moins) des données marquées comme « essentielles ». La Norma IATI contiene una amplia gama de elementos de datos y se invita a su organización a que publique (como mínimo) los datos de los elementos marcados como “básicos”.
Publishing Progress Avancée de la publication Progreso de la publicación
Username already exists in IATI Registry. Nom d’utilisateur existe déjà dans le registre de l’IITA. Nombre de usuario ya existe en el Registro de la IATI.
missing()
translate.missing()  
translate.missing('date')  
translate.missing('language')  
EN FR ES
Missing Manquant(e) Falta
Date Missing Date manquante Falta la fecha
Language Missing Langue manquante Falta el idioma
stickyText()
translate.stickyText('iati_validation')  
translate.stickyText('iati_validation_issue')  
EN FR ES
IATI Validation Validation de l’IITA Validación de la IATI
IATI Validation Issue Problème de validation de l’IITA Problema con la validación de la IATI
webText()
translate.webText('publishing_checklist')  
translate.webText('any_questions_contact_label')  
translate.webText('copyright_label')  
EN FR ES
Publishing Checklist Liste de contrôle avant publication Lista de verificación para publicar datos
ANY QUESTIONS? CONTACT SUPPORT DES QUESTIONS ? CONTACTER L’ASSISTANCE ¿PREGUNTAS? Contactar con el servicio de asistencia
Copyright IATI 2022. All rights reserved. Droits d’auteur de l’IITA 2022. Tous droits réservés. Derechos de autor de la IATI 2022. Todos los derechos reservados.
adminText()
translate.adminText('activity_data')  
translate.adminText('organisation_data')  
translate.adminText('settings')  
EN FR ES
ACTIVITY DATA DONNÉES SUR L’ACTIVITÉ DATOS DE ACTIVIDADES
ORGANISATION DATA DONNÉES SUR L’ORGANISATION DATOS SOBRE LA ORGANIZACIÓN
SETTINGS PARAMÈTRES AJUSTES
registerText() , aboutText(), iatiStandardText(), publishingChecklistText()
translate.registerText('publisher_information.label')  
translate.registerText('publisher_information.hover_text')  
translate.aboutText('use_iati_publisher_to_header')  
translate.aboutText('use_iati_publisher_to_description.one.list_items.one')  
translate.iatiStandardText('download_pdf_header')  
translate.iatiStandardText('download_pdf_description.one')  
translate.publishingChecklistText('update_and_improve_header')  
translate.publishingChecklistText('update_and_improve_description.one')  
EN FR ES
Publisher Information Renseignements sur le signataire Información de la entidad que publica
We refer to organisations who publish IATI data as 'Publishers'. Before publishing data, all organisations need their own 'Publisher Account' on the IATI Registry (iatiregistry.org). Enter your organisation's data here and we'll create your organisation's Publisher Account for you. These details will also be saved here in IATI Publisher. Nous appelons « signataires » les organisations qui transmettent des données à l’IITA. Pour pouvoir publier des données, les organisations doivent avoir leur propre « compte de signataire » dans le registre de l’IITA (iatiregistry.org). Saisissez ici les données de votre organisation et nous créerons son compte de signataire. Nous enregistrons ces données dans IATI Publisher également. Denominamos “entidades que publican” a las organizaciones que facilitan datos a la IATI. Para publicar datos, todas las organizaciones deben contar con su propia “cuenta de entidad que publica” en el Registro de la IATI (iatiregistry.org). Introduzca los datos de su organización aquí y crearemos una cuenta de entidad que publica para su organización. Estos datos también quedarán guardados en IATI Publisher.
Use IATI Publisher to: Utilisez IATI Publisher pour : Utilice IATI Publisher con los siguientes fines:
Register your organisation with an IATI Publisher account Enregistrer votre organisation avec un compte IATI Publisher Registrar su organización con una cuenta de IATI Publisher.
Download PDF of IATI Standard data fields Télécharger les champs de données de la norme de l’IITA au format PDF. Descargar los campos de datos de la Norma IATI en formato PDF
IATI Standard Whilst gathering and preparing your organisation’s IATI data, you may find it helpful to view the following spreadsheets that provide information on all of the data elements in the IATI Standard. You will also be able to view this information as you work your way through completing the forms for each element on IATI Publisher. Lors de la collecte et de la préparation des données de l’IITA de votre organisation, vous jugerez peut-être utile de consulter les feuilles de calcul suivantes, qui contiennent des informations sur les éléments de données de la norme de l’IITA. Vous pourrez également consulter ces informations à mesure que vous remplirez les formulaires pour chaque élément de IATI Publisher. Norma IATI Quizá las siguientes hojas de cálculo, que facilitan información sobre todos los elementos de datos de la Norma IATI, le resulten útiles a la hora de recopilar y preparar los datos de su organización. También tendrá acceso a esta información al rellenar los formularios para cada elemento de IATI Publisher.
Update and improve your data Actualiser et améliorer vos données Actualizar y mejorar sus datos
Once your organisation has published its first dataset, you are encouraged to update and improve your data over time. You should update your data at least every quarter. You should also aim to expand the number of data fields that you provide information for. Read more about improving the quality of IATI data. Une fois que votre organisation a publié son premier ensemble de données, nous vous encourageons à actualiser et améliorer vos données au fil du temps. Vous devez mettre à jour vos données au moins une fois par trimestre. Vous devez également tâcher d’augmenter le nombre de champs de données remplis. En savoir plus amélioration de la qualité des données de l’IITA. Una vez publicado el primer conjunto de datos de su organización, le animamos a que actualice y mejore sus datos con el tiempo. Debe actualizarlos al menos trimestralmente, y también es recomendable aportar información correspondiente a más campos de datos. Más información sobre la mejora de la calidad de los datos de la IATI.
textFromKey()
translate.textFromKey('activity_default.currency.placeholder')  
translate.textFromKey('elements.activities.title.hover_text')  
translate.textFromKey('password_recovery.email_placeholder')  
EN FR ES
Select from dropdown Sélectionnez une entrée du menu déroulant Seleccionar una opción del menú desplegable
A short, human-readable title that contains a meaningful summary of the activity. May be repeated for different languages. For more information Titre concis, lisible par l’être humain et offrant une présentation plus claire des activités de l’organisation. Peut figurer en plusieurs langues. En savoir plus Título conciso, legible para los seres humanos, que contiene un resumen representativo de la actividad. Puede repetirse en varios idiomas. Más información aquí.
Enter your email address Saisissez votre adresse e-mail Indique su dirección de correo electrónico

🔵 2 : Details

2.1 : File content

Each file contains lines based on the context of the line and where the lines appear:

File Description
about.php Contains text for "About" page
activities.php Contains text for "Activities" page. (activity listing page)
activity_default.php Contains text for activity's override default values page
activity_detail.php Contains text for "Activity detail" page
admin.php Contains text for admin nav bar
auth.php Contains text for message that is shown during user auth
buttons.php Contains text for buttons and confirmation modals
common.php Contains repeatable/common text of the application
element_labels.php Contains IATI element names
elements.php Contains IATI element's help text, hover text and placeholder. (Used by jsonSchemas for dynamically generated forms)
elements_common.php Contains IATI element names and common text for elements
email_verification.php Contains text for email related messages
events.php Contains text for events (example: delete, publish, remove, etc)
home.php Contains text for "Home" page
iati_standard.php Contains text for "IATI Standard" page
middleware.php Contains text for error message thrown by middleware.
missing.php Contains text for missing text. Example ('xyz Missing')
organisation.php Contains text for "Organisation detail" page
pagination.php Contains texts : "Prev" and "Next"
password_recovery.php Contains text for "Password recovery" page
publishing_checklist.php Contains text for "Publishing checklist" page
register.php Contains text for user registration component
requests.php Contains text for validation message. (Messages are created in custom Requests)
responses.php Contains text for toast messages. (Messages are created in Controllers)
settings.php Contains text for "Settings" page
sticky.php Contains text for sticky components that are displayed when uploading, downloading files
support.php Contains text for "Support" page
user.php Contains text for user management and all things user related
validation.php Contains text for laravel's default validation
web.php Contains text for pre-login pages nav bar and footer

2.2 : Translation for JsonSchemas

All the forms in the system are generated from either elementJsonSchema.json or organizationJsonSchemas located in root/IATI/Data/.

2.2.1 Original contents

The original contents of the json schema looked like this:

{  
"title": {  
    "name": "title",  
    "label": "title",  
    "multiple": false,  
    "add_more": false,  
    "hover_text": "A short, human-readable title that contains a meaningful summary of the activity. May be repeated for different languages. <a target='_blank' href='https://iatistandard.org/en/iati-standard/203/activity-standard/iati-activities/iati-activity/title/'>For more information</a>",  
    "help_text": "",  
    "show_info_in_title": true,  
    "attributes": {},  
    "sub_elements": {  
    "narrative": {  
    "name": "narrative",  
    "label": "narrative",  
    "type": "text",  
    "placeholder": "",  
    "required": true,  
    "criteria": "mandatory",  
    "add_more": true,  
    "hover_text": "The free text name or description of the item being described. This can be repeated in multiple languages. <a target='_blank' href='https://iatistandard.org/en/iati-standard/203/activity-standard/iati-activities/iati-activity/title/narrative/'>For more information</a>",  
    "help_text": "Provide the title for this activity. For example: \"Water for Women Malawi\".",  
    "attr": {  
        "row": 4  
        },  
    "attributes": {  
        "language": {  
            "name": "language",  
            "label": "language",  
            "type": "select",  
            "placeholder": "Select language",  
            "choices": "Activity/Language.json",  
            "required": true,  
            "criteria": "mandatory",  
            "hover_text": "A code specifying the language of text in this element. It is recommended that wherever possible only codes from ISO 639-1 are used. If not present, the default language is assumed. <a target='_blank' href='https://iatistandard.org/en/iati-standard/203/activity-standard/iati-activities/iati-activity/title/narrative/'>For more information</a>",  
            "help_text": "Select the language of the text you provided in the narrative. If no language is selected, your default language is assumed."  
            }  
        },  
        "sub_elements": {}  
        }  
    }  
},  
....etc 
}

2.2.2 : New contents

In the new jsonSchemas, the values of original attributes : label, hover_text, help_text and placeholder of each element are replaced with complete keys that correspond to original values in the root/lang/*/elements.php file. When fetching any given element to generate forms, the json object are translated using the translateJsonValues() helper function. The new json schema looks like :

{  
"title": {  
    "name": "title",  
    "label": "element_labels.activities.title",  
    "multiple": false,  
    "add_more": false,  
    "hover_text": "elements.activities.title.hover_text",  
    "help_text": "",  
    "show_info_in_title": true,  
    "attributes": [],  
    "sub_elements": {  
        "narrative": {  
        "name": "narrative",  
        "label": "element_labels.activities.narrative",  
        "type": "text",  
        "placeholder": "",  
        "required": true,  
        "criteria": "mandatory",  
        "add_more": true,  
        "hover_text": "elements.activities.title.narrative.hover_text",  
        "help_text": "elements.activities.title.narrative.help_text",  
        "attr": {  
        "row": 4  
    },  
    "attributes": {  
        "language": {  
            "name": "language",  
            "label": "element_labels.activities.language",  
            "type": "select",  
            "placeholder": "elements_common.select_language",  
            "choices": "Activity\/Language.json",  
            "required": true,  
            "criteria": "mandatory",  
            "hover_text": "elements.activities.title.language.hover_text",  
            "help_text": "elements_common.your_default_language_assumed_no_that"  
            }  
        },  
    "sub_elements": []  
    }  
}
... etc 
}
siwhitehouse commented 1 year ago

Thank you @PG-Momik - I think this issue has been opened in response to a request from us at IATI Support to understand the translation process.

Specifically, we would like to know:

The above looks like it describes how the front end displays the translated files. My apologies for any confusion about what we were asking.

PG-Momik commented 1 year ago

@siwhitehouse regarding your queries:

how YI extracts the source string from IATI publihsher


how these are shared with translators

web

image

image


how YI pull the translated files into IATI Publisher

The content of all the google doc files are correctly maintained in a spreadsheet. We then use a script that generates separate language source file for each sheet in each language as shown below: image image


the process for review and amendment of translated files

During implementation there were some lines that resulted in UI inconsistency in the system, this resulted in the initial round of review of the translated text and the changes from the updated translated documents were implemented. Furthermore, we'd love it if you'd proofread lines in Language_All.xls and also the texts in the system itself and inform us of necessary changes.