Main menu

Key collisions inside nested objects

Loco enforces unique IDs, so how can they possibly collide? Suppose you have three assets with unique, dot-separated IDs as follows:

select.fruit = "Select a fruit"
select.fruit.apple = "Apple"
select.fruit.banana = "Banana"

Exporting these as flat keys to your application presents no problem. You would simply access them from your code as fully qualified keys. Something like this (pseudo code):

label = messages["select.fruit"]
options = { apple: messages["select.fruit.apple"], banana: messages["select.fruit.banana"] }

Tip: Exporting JSON, YAML, or PHP with no-expand will generate flat keys for use in your application as shown above.

Expanding dot notation

The example code above is somewhat verbose (requiring the full key paths), but developers might be more annoyed that iterating the options requires knowing them in advance. To solve this problem (amongst others) many platforms support nested objects. Imagine expanding our flat keys to some fictional JSON:

{
    "select": {
        "fruit": "Select a fruit", // COLLISION
        "fruit": {
            "apple": "Apple",
            "banana": "Banana"
        }
    }
}

Problem: The key "select.fruit" cannot co-exist within the same tree as "select.fruit.apple", because "fruit" cannot contain both a string and an object. Your programming language may have ways to achieve this, but to express the data in a serialized format like JSON would require a rethink. For example:

select.fruit.label = "Select a fruit"
select.fruit.options.apple = "Apple"
select.fruit.options.banana = "Banana"

Note the addition of "label" and "options" to separate the string from the options object. This will happily expand to an object with no collisions, as follows (in JSON again):

{
    "select": {
        "fruit": {
            "label": "Select a fruit",
            "options": {
                "apple": "Apple",
                "banana": "Banana"
            }
        }
    }
}

Resolving conflicts

If your application must have a nested structure, but your dot-separated IDs are producing collisions, we recommend you follow the advice above. However - if you're working on multiple platforms, or your IDs cannot change for some other reason, there is another way...

Instead of an impossible object with duplicate keys, Loco's exporter will automatically produce a merged object that looks like this:

{
  "select" : {
    "fruit": {
      "\\0": "Select a fruit",
      "apple": "Apple",
      "banana": "Banana"
    }
  }
}

This structure allows your application to access the scalar value from the key at select.fruit["\0"], but it would be better to prescribe a working structure yourselves, and ensure the object keys in your application match up with their IDs in Loco.

Important: The null key ("\0") shown above is a recent change from using a zero offset ("0"). See the product notice. The legacy merging strategy will continue to be available if you rely on it, but it presents problems if you reimport the structure back into Loco.

See also

Last updated by