Cambiar el idioma de mi Bpmn

Buenos dias,

Soy nuevo en el tema y estoy intentando cambiar el idioma del bpmn en mi proyecto a español, ya intente implementar el ejemplo de i18n para la traduccion pero cuando agregro el modulo “customTranslate”, a la hora de hacer la instancia del modelador sale un error y no me carga nada. Cuando hago debuguer de proceso en la instancia del modelador el error que me sale es que “translate no es una funcion”, no se que pueda estar haciendo mal…

Agradezco la ayuda,

Feliz dia…

Ola, te voy responder en ingles.

You will need two files:
One where you will list the translations, lets name it spanish.js

export default {

    // Labels
    'Activate the global connect tool' : 'Activar a operação de ligação global',
    'StartEvent': 'Inicio'
};

And another file with this:

import translations from './spanish';


export default function customTranslate(template, replacements) {
    replacements = replacements || {};

    // Translate
    template = translations[template] || template;

    // Replace
    return template.replace(/{([^}]+)}/g, function(_, key) {
        return translations[replacements[key]] || '{' + key + '}';
    });
}

(You can modify the code above, this is not the same as in the example because it wasn’t translating everything as it should)

Then in your index.js (main file where you instantiate the viewer/modeler:

import spanishTranslate from './translate/customTranslate';
var customTranslateModule = {
    translate: [ 'value', spanishTranslate ]
};

var bpmnModeler = new BpmnModeler({
    container: '#js-canvas',
    additionalModules: [
        customTranslateModule
    ]
});

If you can’t still make it work, try to share your project here so people can debug it.

2 Likes

Buenas tardes Raquel,

Muchas gracias por responder, voy a probar y te cuento el resultado… Creo que puede ser por la versión que tengo de mi netbeans no acepta “import” y “export”, los estaba utilizando de otra manera que puede no ser la correcta, veré que puedo hacer.

Muchas Gracias por tu ayuda!

Please keep the communication in English so everyone can participate. Thanks.

Good morning,
I again, try my project with the help you sent me but still it does not work, it stops working when I add the new module.
I share my project in case anyone can verify the error you may have.

Thank you very much.

Index.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>BPMN</title>

        <!-- required modeler styles -->
        <link rel="stylesheet" href="https://unpkg.com/bpmn-js@2.5.1/dist/assets/diagram-js.css" />
        <link rel="stylesheet" href="https://unpkg.com/bpmn-js@2.5.1/dist/assets/bpmn-font/css/bpmn.css" />

        <!-- modeler distro -->
        <script src="https://unpkg.com/bpmn-js@2.5.1/dist/bpmn-modeler.development.js"></script>
        <%--<script src="https://unpkg.com/bpmn-js@2.4.1/dist/bpmn-viewer.development.js"></script>--%>

        <!-- needed for this example only -->
        <script src="https://unpkg.com/jquery@3.3.1/dist/jquery.js"></script>

        <!-- example styles -->
        <style>
            * {
                box-sizing: border-box;
            }

            body, html {

                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;

                font-size: 12px;

                height: 100%;
                padding: 0;
                margin: 0;
            }

            a:link {
                text-decoration: none;
            }

            .content,
            .content > div {
                width: 100%;
                height: 100%;
            }

            .content > .message {
                text-align: center;
                display: table;

                font-size: 16px;
                color: #111;
            }

            .content > .message .note {
                vertical-align: middle;
                text-align: center;
                display: table-cell;
            }

            .content .error .details {
                max-width: 500px;
                font-size: 12px;
                margin: 20px auto;
                text-align: left;
            }

            .content .error pre {
                border: solid 1px #CCC;
                background: #EEE;
                padding: 10px;
            }

            .content:not(.with-error) .error,
            .content.with-error .intro,
            .content.with-diagram .intro {
                display: none;
            }


            .content .canvas,
            .content.with-error .canvas {
                visibility: hidden;
            }

            .content.with-diagram .canvas {
                visibility: visible;
            }

            .buttons {
                position: fixed;
                bottom: 20px;
                left: 20px;

                padding: 0;
                margin: 0;
                list-style: none;
            }

            .buttons > li {
                display: inline-block;
                margin-right: 10px;
            }
            .buttons > li > a {
                background: #DDD;
                border: solid 1px #666;
                display: inline-block;
                padding: 5px;
            }

            .buttons a {
                opacity: 0.5;
            }

            .buttons a.active {
                opacity: 2.0;
            }

            .Subir {
                cursor: pointer;
            }

            .highlight:not(.djs-connection) .djs-visual > :nth-child(1) {
                fill: green !important; /* color elements as green */
            }
            .highlight-overlay {
                background-color: green; /* color elements as green */
                opacity: 0.4;
                pointer-events: none; /* no pointer events, allows clicking through onto the element */
                border-radius: 10px;
            }
        </style>

    </head>
    <body>

        <div class="content" id="js-drop-zone">

            <div class="message intro">
                <div class="note">
                    Drop BPMN diagram from your desktop or <a id="js-create-diagram" href>Create a new diagram</a> to get started.
                </div>
            </div>

            <div class="message error">
                <div class="note">
                    <p>Ooops, we could not display the BPMN 2.0 diagram.</p>

                    <div class="details">
                        <span>Cause of the problem</span>
                        <pre></pre>
                    </div>
                </div>
            </div>

            <div class="canvas" id="canvas"></div>

        </div>

        <%--<div class="canvas" id="canvas"></div>--%>
        <ul class="buttons">
            <li>
                <a id="js-download-diagram" href="" title="Descargar diagrama BPMN">
                    Diagrama BPMN
                </a>
            </li>
            <li>
                <a id="js-download-svg" href="" title="Descargar imagen BPMN">
                    Imagen BPMN
                </a>
            </li>

            <li>
                <form id="formulario" onsubmit="exportDiagram();" method="post" action="Bpmn.jsp">
                    <input type="hidden" id="parametro" name="parametro"> 
                    <input type="submit" value="Guardar XML" class="Subir" title="Guardar XML" ></input>
                </form>
            </li>
            <li>
                <form onsubmit="" method="post" action="Bpmn.jsp">
                    <input type="submit" value="Cargar XML" class="Subir" title="Cargar XML" ></input>
                </form>

            </li>
        </ul>

        <script language="javascript">

            <%
                String valor = request.getParameter("parametro");
            %>
                
            //import customTranslate from './customTranslate';
            var customTranslate = './customTranslate';

            var container = $('#js-drop-zone');
            <%if (valor == null || valor.equals("")) {%>
            var diagramUrl = 'https://cdn.rawgit.com/bpmn-io/bpmn-js-examples/dfceecba/starter/diagram.bpmn';
            <%} else {%>
            diagramUrl = 'https://cdn.rawgit.com/bpmn-io/bpmn-js-examples/dfceecba/starter/diagram.bpmn';
            <%}%>
            //var diagramUrl = document.getElementById("parametro").value;
            //var x;

            var customTranslateModule = {
                translate: ['value', customTranslate]
            };

            // modeler instance
            var bpmnModeler = new BpmnJS({
                container: '#canvas',
                additionalModules: [                 //when he added this module it does not work for me
                    customTranslateModule 
                ]

            });
            
            function createNewDiagram() {
                openDiagram(diagramUrl);
            }

            /**
             * Save diagram contents and print them to the console.
             */
            function exportDiagram() {
                bpmnModeler.saveXML({format: true}, function (err, xml) {
                    if (err) {
                        return console.error('could not save BPMN 2.0 diagram', err);
                    }
                    alert('El diagrama se guardara en la base de datos en formato XML!');
                    console.log('DIAGRAM', xml);
                    //x = xml;
                    // form = document.getElementById("formulario");
                    document.getElementById("parametro").value = xml;
                    // form.parametro.value = xml;   

            <%
                /**
                 * if (valor != null) {
                 * ConsultasGenerales.insertarXmlBpmn(valor);
                 * ConsultasGenerales.crearArchivoBpmn(valor);
                 * request.setAttribute("parametro", valor); } else {
                 * System.out.println("..."); }
                 *
                 */
            %>
                });
            }
            /**
             * Open diagram in our modeler instance.
             *
             * @param {String} bpmnXML diagram to display
             */
            function  openDiagram(bpmnXML) {
                // import diagram
                bpmnModeler.importXML(bpmnXML, function (err) {

                    if (err) {
                        container
                                .removeClass('with-diagram')
                                .addClass('with-error');

                        container.find('.error pre').text(err.message);

                        console.error(err);
                    } else {
                        container
                                .removeClass('with-error')
                                .addClass('with-diagram');
                    }


                });
            }
            // load external diagram file via AJAX and open it
            $.get(diagramUrl, openDiagram, 'text');
            // wire save button
            $('#save-button').click(exportDiagram);

            function saveSVG(done) {
                bpmnModeler.saveSVG(done);
            }

            function saveDiagram(done) {

                bpmnModeler.saveXML({format: true}, function (err, xml) {
                    done(err, xml);
                });
            }

            function registerFileDrop(container, callback) {

                function handleFileSelect(e) {
                    e.stopPropagation();
                    e.preventDefault();

                    var files = e.dataTransfer.files;

                    var file = files[0];

                    var reader = new FileReader();

                    reader.onload = function (e) {

                        var xml = e.target.result;

                        callback(xml);
                    };

                    reader.readAsText(file);
                }

                function handleDragOver(e) {
                    e.stopPropagation();
                    e.preventDefault();

                    e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
                }

                container.get(0).addEventListener('dragover', handleDragOver, false);
                container.get(0).addEventListener('drop', handleFileSelect, false);
            }


            // file drag / drop ///////////////////////

            // check file api availability
            if (!window.FileList || !window.FileReader) {
                window.alert(
                        'Looks like you use an older browser that does not support drag and drop. ' +
                        'Try using Chrome, Firefox or the Internet Explorer > 10.');
            } else {
                registerFileDrop(container, openDiagram);
            }

            // bootstrap diagram functions

            $(function () {

                $('#js-create-diagram').click(function (e) {
                    e.stopPropagation();
                    e.preventDefault();

                    createNewDiagram();
                });

                var downloadLink = $('#js-download-diagram');
                var downloadSvgLink = $('#js-download-svg');

                $('.buttons a').click(function (e) {
                    if (!$(this).is('.active')) {
                        e.preventDefault();
                        e.stopPropagation();
                    }
                });

                function setEncoded(link, name, data) {
                    var encodedData = encodeURIComponent(data);

                    if (data) {
                        link.addClass('active').attr({
                            'href': 'data:application/bpmn20-xml;charset=UTF-8,' + encodedData,
                            'download': name
                        });
                    } else {
                        link.removeClass('active');
                    }
                }

                var exportArtifacts = debounce(function () {

                    saveSVG(function (err, svg) {
                        setEncoded(downloadSvgLink, 'diagram.svg', err ? null : svg);
                    });

                    saveDiagram(function (err, xml) {
                        setEncoded(downloadLink, 'diagram.bpmn', err ? null : xml);
                    });
                }, 500);

                bpmnModeler.on('commandStack.changed', exportArtifacts);
            });



            // helpers //////////////////////

            function debounce(fn, timeout) {

                var timer;

                return function () {
                    if (timer) {
                        clearTimeout(timer);
                    }

                    timer = setTimeout(fn, timeout);
                };
            }

            function myFunction() {
                return;
            }

        </script>

        <!--
          Thanks for trying out our BPMN toolkit!
          This example uses the pre-built distribution of the bpmn-js modeler.
          Consider rolling your own distribution to have more flexibility
          regarding which features to include.
          Checkout our advanced examples section to learn more:
          * https://github.com/bpmn-io/bpmn-js-examples#advanced
          To get a bit broader overview over how bpmn-js works,
          follow our walkthrough:
          * https://bpmn.io/toolkit/bpmn-js/walkthrough/
          Related starters:
          * https://raw.githubusercontent.com/bpmn-io/bpmn-js-examples/starter/viewer.html
        -->
    </body>
</html>

customTranslate.js

import translations from './translations';


export default function customTranslate(template, replacements) {
    replacements = replacements || {};

    // Translate
    template = translations[template] || template;

    // Replace
    return template.replace(/{([^}]+)}/g, function (_, key) {
        return translations[replacements[key]] || '{' + key + '}';
    });
}

translations

export default {
    // Labels
  'Activate the global connect tool' : 'Activar la herramienta de conexión global',
  'Append {type}': 'Añadir {tipo}',
  'Add Lane above': 'Añadir línea arriba',
  'Divide into two Lanes': 'Divida en dos carriles',
  'Divide into three Lanes': 'Divida en tres carriles',
  'Add Lane below': 'Agregar línea debajo',
  'Append compensation activity': 'Anexar actividad de compensación',
  'Change type': 'Cambiar tipo',
  'Connect using Association': 'Conectar utilizando la Asociación',
  'Connect using Sequence/MessageFlow or Association': 'Conectar utilizando secuencia / flujo de mensajes o asociación',
  'Connect using DataInputAssociation': 'Conectar usando la Asociación de Entrada de Datos',
  'Remove': 'Retirar',
  'Activate the hand tool': 'Activar la herramienta de mano',
  'Activate the lasso tool': 'Activar la herramienta Lazo',
  'Activate the create/remove space tool': 'Activar la herramienta de crear / eliminar espacio',
  'Create expanded SubProcess': 'Crear Subproceso expandido',
  'Create IntermediateThrowEvent/BoundaryEvent' : 'Crear Evento de Tiro Intermedio / Evento de Límite',
  'Create Pool/Participant': 'Crear grupo / participante',
  'Parallel Multi Instance': 'Instancia múltiple paralela',
  'Sequential Multi Instance': 'Instancia múltiple secuencial',
  'Loop': 'Lazo',
  'Ad-hoc': 'Ad-hoc',
  'Create {type}': 'Crear {tipo}',
  'Task': 'Tarea',
  'Send Task': 'Enviar tarea',
  'Receive Task': 'Recibir tarea',
  'User Task': 'Tarea de usuario',
  'Manual Task': 'Tarea manual',
  'Business Rule Task': 'Tarea de regla empresarial',
  'Service Task': 'Tarea de servicio',
  'Script Task': 'Tarea de script',
  'Call Activity': 'Actividad de llamada',
  'Sub Process (collapsed)': 'Subproceso (colapsado)',
  'Start Event': 'Evento de inicio',
  'Intermediate Throw Event': 'Evento de Lanzamiento Intermedio',
  'End Event': 'Fin del evento',
  'Message Start Event': 'Evento de inicio de mensaje',
  'Timer Start Event': 'Evento de inicio del temporizador',
  'Conditional Start Event': 'Evento de inicio condicional',
  'Signal Start Event': 'Evento de inicio de señal',
  'Error Start Event': 'Error al iniciar el evento',
  'Escalation Start Event': 'Evento de inicio de escalamiento',
  'Compensation Start Event': 'Evento de Compensación',
  'Message Start Event (non-interrupting)': 'Evento de inicio de mensaje (sin interrupción)',
  'Timer Start Event (non-interrupting)': 'Evento de inicio del temporizador (sin interrupción)',
  'Conditional Start Event (non-interrupting)': 'Evento de inicio condicional (sin interrupción)',
  'Signal Start Event (non-interrupting)': 'Evento de inicio de señal (sin interrupción)',
  'Escalation Start Event (non-interrupting)': 'Evento de inicio de escalamiento (sin interrupción)',
  'Message Intermediate Catch Event': 'Evento de captura intermedia del mensaje',
  'Message Intermediate Throw Event': 'Evento de Lanzamiento Intermedio del Mensaje',
  'Timer Intermediate Catch Event': 'Evento de captura intermedia del temporizador',
  'Escalation Intermediate Throw Event': 'Evento de Lanzamiento Intermedio de Escalada',
  'Conditional Intermediate Catch Event': 'Evento de captura intermedia condicional',
  'Link Intermediate Catch Event': 'Enlace Evento de captura intermedio',
  'Link Intermediate Throw Event': 'Evento de Lanzamiento Intermedio de Enlace',
  'Compensation Intermediate Throw Event': 'Compensación Evento de tiro intermedio',
  'Signal Intermediate Catch Event': 'Evento de captura intermedia de señal',
  'Signal Intermediate Throw Event': 'Evento de lanzamiento intermedio de señal',
  'Message End Event': 'Evento final del mensaje',
  'Escalation End Event': 'Evento final de escalada',
  'Error End Event': 'Evento de final de error',
  'Cancel End Event': 'Cancelar evento final',
  'Compensation End Event': 'Evento final de compensación',
  'Signal End Event': 'Evento final de señal',
  'Terminate End Event': 'Terminar evento final',
  'Message Boundary Event': 'Evento de límite de mensaje',
  'Message Boundary Event (non-interrupting)': 'Evento de límite de mensaje (sin interrupción)',
  'Timer Boundary Event': 'Evento límite de temporizador',
  'Timer Boundary Event (non-interrupting)': 'Evento límite de temporizador (sin interrupción)',
  'Escalation Boundary Event': 'Evento límite de escalada',
  'Escalation Boundary Event (non-interrupting)': 'Evento de límite de escalada (sin interrupción)',
  'Conditional Boundary Event': 'Evento de límite condicional',
  'Conditional Boundary Event (non-interrupting)': 'Evento de límite condicional (sin interrupción)',
  'Error Boundary Event': 'Evento de límite de error',
  'Cancel Boundary Event': 'Cancelar evento de límite',
  'Signal Boundary Event': 'Evento de límite de señal',
  'Signal Boundary Event (non-interrupting)': 'Evento de límite de señal (sin interrupción)',
  'Compensation Boundary Event': 'Evento Límite de Compensación',
  'Exclusive Gateway': 'Pasarela exclusiva',
  'Parallel Gateway': 'Pasarela paralela',
  'Inclusive Gateway': 'Pasarela inclusiva',
  'Complex Gateway': 'Pasarela compleja',
  'Event based Gateway': 'Pasarela basada en eventos',
  'Transaction': 'Transacción',
  'Sub Process': 'Subproceso',
  'Event Sub Process': 'Evento Subproceso',
  'Collapsed Pool': 'Grupo derrumbado',
  'Expanded Pool': 'Grupo ampliado',

  // Errors
  'no parent for {element} in {parent}': 'no padre para {elemento} en {padre}',
  'no shape type specified': 'ningún tipo de forma especificada',
  'flow elements must be children of pools/participants': 'los elementos de flujo deben ser hijos de las piscinas / participantes',
  'out of bounds release': 'lanzamiento fuera de límites',
  'more than {count} child lanes': 'más de {contar} carriles secundarios',
  'element required': 'elemento requerido',
  'diagram not part of bpmn:Definitions': 'diagrama que no forma parte de bpmn: Definiciones',
  'no diagram to display': 'no hay diagrama para mostrar',
  'no process or collaboration to display': 'ningún proceso o colaboración para mostrar',
  'element {element} referenced by {referenced}#{property} not yet drawn': 'elemento {elemento} referenciado por {referido} # {propiedad} aún no dibujado',
  'already rendered {element}': 'ya procesado {elemento}',
  'failed to import {element}': 'no se pudo importar {elemento}'
};

What error are you getting? How are you bundling your custom translate module?

good morning,
this is the error that I can detect when I add the translation module

image

image

Hola Arenas buendía! He revisado todo tu hilo y veo que en tu ultimo post ya no te respondieron. Pudiste implementar la traducción del bpmn? Yo he tratado de hacer todos los pasos pero sin éxito. Ojala lo hayas logrado tu.

Saludos!