Browser/user language in pure Elm app

#1

Hi! :wave:

I have a small app where I’m trying to develop exclusively with elm reactor and elm make —output=index.html

The application has language translations and localization of numbers, and I would like to choose the default language when booting the app to match the browser language of the user.

In JS, this information is in navigator.language: https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language

Is there any way to get this language with pure Elm?

(I know how to do it with ports and a custom HTML, but I want to keep using elm-reactor)

Thank you, and have a nice day!

#2

Unfortunately no. You’re stuck if you want to keep the reactor. There isn’t a way in the reactor to get the compiled javascript as a url, you only have the compiled to html version available, but… If you want to keep elm-reactor for its simpilicity, you can have a look at parcel: it’s a zero config bundler. Just create a index.html and index.js (that import Main.elm). Then you can use ports & all…

1 Like
#3

There are two tricks that I can think of:

  1. If you have a server to talk to, you could make an HTTP request to it on init and have it return to you your Accept-Language header. You could also use https://httpbin.org/headers if you trust it as it accepts CORS requests. For example https://ellie-app.com/59jy97tDFbPa1

  2. Decode an event that alllows you to access window.navigator.language, for example using the first mouse move: https://ellie-app.com/59jz3HR7FhJa1 (you should remove the subscription once you have the language though).
    You could also ask the user to press a key or click a button on init and get it the same way (maybe using a nice welcome banner as a pretext).

subscriptions : Model -> Sub Msg
subscriptions model =
    Events.onMouseMove (Decode.map GotLang decodeLang)


decodeLang : Decode.Decoder String
decodeLang =
    Decode.at [ "view", "navigator", "language" ] Decode.string

At last note that some browsers differentiate the browser interface language from pages content language, so the two techniques may give different results.

2 Likes
#4

Thanks @dmy, very useful.

I’ve made a little example by manually triggering focus, not requiring user interaction: https://ellie-app.com/59kfMKvP97Ka1 A small issue is that the app focus is shown, which you could hide with CSS outline or trigger a blur from Elm. All solvable.

This is a very interesting approach, it could probably be used for accessing all kinds of useful information in navigator, like navigator.onLine.

In any case, for a more serious app it is quite clear that Flags and ports would be the easy way to go for this.

There is probably a way to have an entry point for compiling with a custom HTML, and another file with defaults for loading the app with elm reactor. That could work for flags information.

1 Like
#5

I can recommend having a look at elm-live as a replacement for reactor. It can use custom html.

I’ve used it in a project of mine. You can have a look at my npm start script. start:no-sw stands for “no service worker”, since sometimes I want to test the app without caching or other SW features.

2 Likes
#6

If you are down to building the compiler yourself, we extended the reactor to do exactly what you need:

We added two flags: a js and a debug flag. Getting the js in debug mode from the reactor would then look like this: http://localhost:8000/src/Main.elm?output=js&debug=true

You can find the extened compiler with build instructions here and an example here

2 Likes
closed #7

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.