Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translation keys are ignored when dot format and nested format are mixed #1456

Open
marianschiller93 opened this issue Nov 20, 2023 · 0 comments

Comments

@marianschiller93
Copy link

marianschiller93 commented Nov 20, 2023

Current behavior

If the dot format and the nested format are mixed, a translation key in dot format is ignored if there is a nested block with a prefix of the translation key.

In this example

{
    "i18n.fruits.apple": "Apfel",
    "i18n.fruits.lemon": "Zitrone",
    "i18n.fruits.lime": "Limette",
    "i18n.fruits.yellowWatermelon": "Gelbe Wassermelone",
    "i18n.fruits.pomegranate": "Granatapfel",
    "i18n.fruits.orange": "Orange",
    "i18n.fruits.strawberry": "Erdbeere",
    "i18n.fruits": {
        "cherry": "Kirsche"
    }
}

the nested block

"i18n.fruits": {
    "cherry": "Kirsche"
}

swallows all "i18n.fruits" translations. Only the key "i18n.fruits.cherry" is translated.

Expected behavior

If the dot format and the nested format are combined, the translation keys should be merged.

How do you think that we should fix this?

In the getValue method of the TranslateDefaultParser the target variable is set to the nested object whose key is a prefix of the translation key. Thus the keys of the previous target (initially the complete json file) are ignored. One option here would be to merge the matching keys of the previous target.

target = {
  ...target[key],
  ...Object.fromEntries(
    Object.entries(target)
      .filter(([k]) => k.startsWith(key + '.'))
      .map(([k, v]) => [k.slice(key.length + 1), v])
  )
};

Here is a suggestion for the complete adapted getValue method (v15.0.0):

getValue(target: any, key: string): any {
  let keys = typeof key === 'string' ? key.split('.') : [key];
  key = '';
  do {
    key += keys.shift();
    if (isDefined(target) && isDefined(target[key]) && (typeof target[key] === 'object' || !keys.length)) {
      target = {
        ...target[key],
        ...Object.fromEntries(
          Object.entries(target)
            .filter(([k]) => k.startsWith(key + '.'))
            .map(([k, v]) => [k.slice(key.length + 1), v])
        )
      };
      key = '';
    } else if (!keys.length) {
      target = undefined;
    } else {
      key += '.';
    }
  } while (keys.length);

  return target;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant