ChristophP / elm-i18next

https://package.elm-lang.org/packages/ChristophP/elm-i18next/latest
BSD 3-Clause "New" or "Revised" License
66 stars 12 forks source link

Modify and encode translations #29

Closed nathanPro closed 2 years ago

nathanPro commented 3 years ago

Hello!

I used this library in an application in which I had to change translations, i.e. add entries and update translations. Since I wanted users to be able to download the translations they created, so they could save their status, I also had to create an encode function. I added the following functions to the API:

toList : Translations -> List ( String, String )
insert : String -> String -> Translations -> Translations

Is there interest in adding some of this functionality to the project?

If that is the case, I think we have an interesting API design decision to make.

You see, the insert function assumes we are inserting a key and a value pair: it treats a Translations as a Dict of keys and values. But what should the output of insert "root" "bla" t of a Translations t obtained from parsing

{ "root" : { "child" :"string" } }

? As I simply forward it to the dict, what I obtain is

{
  "root.child" : "string",
  "root" : "bla"
}

but maybe we should actually return

{ "root" :  "bla" }

Having said all of that, I think that to expose this functionality, we must choose how much the nesting matters to us. If we regard it simply as a way to avoid prefix duplication in files, I think the API mentioned above is reasonable (including the toList function).

If we regard the nesting as an important part of our API, then toList should be toTree, and the insert should receive a "path" of prefixes as key, or something similar.

This also comes up if we decide to expose an encode function. encode : Translations -> Json.Encode.Value Although the signature of encode does not change in both cases, the output it produces is influenced by this decision: on the first case, it seems quite reasonable to just output the underlying dict. In the second case, it seems reasonable to output a nested structure. In other words, should we output

{ "root" : { "child" :"string" } }

or

{ "root.child" :"string" } }

from the structure mentioned above?

Thanks in advance, Nathan

ChristophP commented 3 years ago

Hi @nathanPro ,

About encoding: I see that encoding translations would be useful for people to download their edited Translations. The un-nesting in the dict that is used in Translations is really just an implementation detail, because it was easier to access the dict in a "flat" way than to have to recursively go all the way to the bottom. All the regular translation files are nested and I think that is an intended to be a mechanism for grouping translations together. Therefore I would expect encode to restore the nesting of a file. We could check this with a test that checks if a file is the same again, when decoding it to Translations and then encoding it again.

About insert, and toList to be able to edit the translations tree. What about delete you probably need a way to remove keys too don't you? I think the problem is that Tree is opaque and cannot be matched against or modified at the moment. If it was exposed modifying it would be easy for you, correct? The Translations type was never really intended to be modified, that's why it is hard to do at the moment. Most people don't need that but if you're building an editor you certainly do. Another way of solving your problem would be to keep around your tree in a plain flat Dict while it is being edited and have a (self-written) function which converts it to Translations for display or when someone clicks download. Would that work for you as well?

ChristophP commented 2 years ago

Since this is pretty old and got not responses in over a year I am closing this. Please reopen when it becomes relevant again.