Skip to content
Advertisement

How to prevent twig from auto escaping Japanese characters?

I am trying to display product’s arrival date. I’m using moment.js to format YYYY/MM/DDdate string to Japanese local string. My javascript code is included in a twig file:

<script>
        moment.locale('ja');
        let updateArrivalDate = function() {
            $('.arrival-date').each(function() {
                let $this = $(this);
                $selectDate = $this.next().next().find('select').eq(0);
                $selectTime = $this.next().next().find('select').eq(1);
                var text = $selectDate.val();
                var date = moment(text, 'YYYY/MM/DD');
                if (date.isValid()) {
                    $this.text(date.format('{{ 'YYYY年M月D日 (dd)'|raw }}'))
                }
            });
        };
        $(document).ready(function() {
          updateArrivalDate();
            $('select').on('change', function() {
                updateArrivalDate();
            });
        });
    </script>

As you can see, I used raw filter to prevent twig from escaping Japanese characters. Nevertheless, twig escapes special characters anyway and the text is garbled:

garbled Japanese characters due to twig auto-escaping

Of course, it would be solved if I moved the above snippet to an external file. But seriously, is there not a way to stop twig escaping Japanese characters? Why is raw filter not working?

Advertisement

Answer

Import moment ja locale from the cdn (or from npm/yarm installed package) as seen in https://momentjs.com/docs/#/i18n/

If you use a cdn hosted js then use the following code:

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js" integrity="sha256-4iQZ6BVL4qNKlQ27TExEhBN1HFPvAvAMbFavKKosSWQ=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/locale/ja.js" integrity="sha256-CFWtR1hGN/5Vc+kcJkqeMFND0g6gFFZdnSqUtdL7WOQ=" crossorigin="anonymous"></script>

Then instead of:

 $this.text(date.format('{{ 'YYYY年M月D日 (dd)'|raw }}'))

Use:

 var date = moment(text, 'YYYY/MM/DD');
 $this.html(date.locale('ja').format('LL (dd)'))

And remove the:

        moment.locale('ja');

line

So your script will be:

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js" integrity="sha256-4iQZ6BVL4qNKlQ27TExEhBN1HFPvAvAMbFavKKosSWQ=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/locale/ja.js" integrity="sha256-CFWtR1hGN/5Vc+kcJkqeMFND0g6gFFZdnSqUtdL7WOQ=" crossorigin="anonymous"></script>
<script>
        let updateArrivalDate = function() {
            $('.arrival-date').each(function() {
                let $this = $(this);
                $selectDate = $this.next().next().find('select').eq(0);
                $selectTime = $this.next().next().find('select').eq(1);
                let text = $selectDate.val();
                let date = moment(text, 'YYYY/MM/DD');
                if (date.isValid()) {
                    $this.text(date.locale('ja').format('LL (dd)'))
                }
            });
        };
        $(document).ready(function() {
          updateArrivalDate();
            $('select').on('change', function() {
                updateArrivalDate();
            });
        });
    </script>

Consult the example bellow containing only the formating regarding the language:

$(document).ready(function(){
 $("#date").html(moment().locale('ja').format('LL (dd)'))
});
<script src="https://momentjs.com/downloads/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/locale/ja.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="date"></div>

So you let moment to format the date and avoid any complexity with js/twig. Just keep it simple and let the js to do its job instead of mixing them all together.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement