Internationalization in views and components


#1

im trying to make use of the built in internationalization in adonis, and sometimes it works, but sometimes it fails. one of my components look like this:

    @each(challenge in challenges)

    <div class="c-media mt-2">
        <div class="c-media__image col-sm-2">
            <img src="{{assetsUrl('/img/icons/send.svg')}}" alt="Dumbell icon">
             @if(challenge.campaignType == 1)
                <div class="label">Utfordring</div>
            @elseif(challenge.campaignType == 2) 
                <div class="label">Enkeltbudskap</div>
            @elseif(challenge.campaignType == 3) 
                <div class="label">Interessemelding</div>
            @endif

        </div>

    @endeach

when i try to put
{{ antl.formatMessage('dictionary.challenge') }}
instead of Utfordring i get this error message:
TypeError: this.context.resolve(...).formatMessage is not a function

the component is being used as a self closing component in edge.


#2

Anyone? Would be nice to get some kind of reply to this so I know if I have to check out other solutions.


#3

You should make a global middleware , something like this:

App/Middleware/LocaleSwitch.js

'use strict'

class LocaleSwitch {
  async handle ({ request, locale, session, antl }, next) {
    const _locale = session.get('locale') || locale
    antl.switchLocale(_locale)
    await next()
  }
}

module.exports = LocaleSwitch

kernel.js

const globalMiddleware = [
  ...
  'App/Middleware/LocaleSwitch',
  ...
]

#4

When you say it fails sometimes. What exactly that mean?


#5

It looks like it doesnt work with a component getting rendered in a view. thats when I got the error message.

it is used like this
@!component('components.dash-challenges', title="Aktive utfordringer", href="/kampanjer/utfordringer", challenges = challenges)

and when I try to use the antl.formatMessage inside that component I get the error message.


#6

Ohh yeah because components scope is isolated, so you’ll have to pass antl as a prop to the component

@!component('components.dash-challenges', antl = antl)

#7

thank you. all good and working now. might want to update the docs with this?


#8

I have one more question about the antl and components. I have a tiny component named stat-box that looks like this

<div class="card card--inline mt-1 col-sm-3">
<div class="card-block">
    <h4 class="card-title">{{title}}</h4>
    <p>{{content}}</p>
</div>

In my main section I make use of it like this

        @!component('components.stat-box', 
          title="I faresonen", 
          content = stats.danger_users + ' brukere har kun trent for mellom 30 og 60 dager siden.' 
          )
        @!component('components.stat-box', 
          title="Inaktive brukere", 
          content = stats.inactive_users + ' brukere har ikke trent ila. de siste 60 dagene.' 
          )

and I have several more like this. Is there any way to pass the title and content with antl.formatMessage or do I have to move the HTML from the component back into the main section?

  1. question: Is there any way that I can give the option to the users to change the locale and language that my site is shown in?

Thank you!


#9
  1. You can simply say
@!component(
  'components.stat-box',
  title = antl.formatMessage('reference-to-message')
)
  1. You can use the Database driver, instead of the file driver and create a view, which allows users to update the database values. You will have to call Antl.bootLoader() everytime the values inside the database changes.

#10

Thanks! I must have had some typo several times because I couldnt get the title = antl.format… to work, but now it does. Regarding the second question, I now how english and norwegian and fallback folders with the different translations in .json, but I was wondering if there was some kind of way to easily switch between the two languages? The values in the database is only in Norwegian right now, but we will have som english speaking users so it would be nice to be able to switch between the locale, regardless of what the system/browser language is set to. is this possible?


#11

Any answers to last question?


#12

Yup follow these steps.

  1. Create a dropdown with the list of available languages.
  2. On click, set a cookie with the selected language.
  3. Create a global middleware, which reads the previously set cookie value and set the user language before the request reaches your controller.

Middleware will call

antl.switchLocale(cookieValue || defaultLanguage)

#13

Also checkout this article, I recently wrote https://medium.com/virk-me/multilingual-website-using-adonisjs-23abea1a373


#14

Thanks! Super easy once I understood how to do it.