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

Double fix for 1395 issue #1399

Merged

Conversation

lgordey
Copy link

@lgordey lgordey commented Feb 19, 2020

@mgroenhoff @jamuhl
Now i feel guilty >_<
Initiative is really punishable :)

I hope this solves the problem #1398

@jamuhl
Copy link
Member

jamuhl commented Feb 19, 2020

Don't worry...you added value to this lib...contributions are highly appreciated 👍

I will check this tomorrow...

@jamuhl
Copy link
Member

jamuhl commented Feb 20, 2020

@mgroenhoff could you please review if this solves your issue?

@mgroenhoff
Copy link
Contributor

No sorry, it does not. I've set up some quick tests to illustrate the problem:

const assert = require("assert");

require("./index").init({
    // debug: true,
    lng: "en",
    keySeparator: "→",
    nsSeparator: "§",
    pluralSeparator: "‗",
    contextSeparator: "»",
    resources: {
        en: {
            translation: {
                "foo $t(bar)": "translated foo $t(bar, {'a': 'baz'})",
                "foo $t(bar, {'a': 'a'}) a": "translated foo $t(bar, {'a': {{a}}})",
                "foo $t(bar, {'a': {{a}}}) a": "translated foo $t(bar, {'a': {{a}}})",
                "foo {{bar}}": "translated foo {{bar}}",
                "bar": "translated bar {{a}}",
                "bar1, bar2": "translated bar1, translated bar2",

                "foo $t(bar1, bar2)": "translated foo $t(bar1, bar2)",
                "foo $t(bar1, bar2, {})": "translated foo $t(bar1, bar2, {})",
                "foo $t(bar1, bar2, {'a': 'a'})": "translated foo $t(bar1, bar2, {'a': 'a'})",
                "foo $t(bar1, bar2, {'a': {{a}}})": "translated foo $t(bar1, bar2, {'a': {{a}}})",
            }
        }
    }
}, (_err, t) => {
    const t1 = "translated foo translated bar baz";
    assert.strictEqual(t("foo $t(bar)"), t1);
    assert.strictEqual(t("foo $t(bar, {'a': 'a'}) a", { a: "baz" }), t1);
    assert.strictEqual(t("foo $t(bar, {'a': {{a}}}) a", { a: "baz" }), t1);
    assert.strictEqual(t("foo {{bar}}", { bar: "$t(bar, {'a': {{b}} })", a: "baz" }), t1);

    const t2 = "translated foo translated bar1, translated bar2";
    assert.strictEqual(t("foo $t(bar1, bar2)"), t2); // <-- assertion
    assert.strictEqual(t("foo $t(bar1, bar2, {})"), t2);
    assert.strictEqual(t("foo $t(bar1, bar2, {'a': 'a'})"), t2);
    assert.strictEqual(t("foo $t(bar1, bar2, {'a': {{a}}})"), t2);
});

Changing the return statement into the following would fix the issue. Please note that this is a quick fix because it tries to see if the part after the last comma kinda looks like a JSON object and if it doesn't it'll put it back.

if (!/^\s*\{.*\}\s*$/.test(optionsString)) {
	key += "," + optionsString;
}

Again like i said in the original issue, the real fix for this would be to make the separation character used to separate the key and the options string configurable. As you can see in the above example i like the keys to match the values as much as possible and i use rarely used Unicode characters for other separation characters. For example the default value for nsSeparator is : which would mess up the keys big time.

I guess you could also refactor the entire handleHasOptions function and prevent deconstructing and reconstructing the key all the time (using lastIndexOf + slice i.s.o. split + pop + join) but i'll leave that up to you.

@jamuhl jamuhl merged commit 04637a6 into i18next:master Feb 20, 2020
@jamuhl
Copy link
Member

jamuhl commented Feb 20, 2020

published in i18next@19.3.0

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

Successfully merging this pull request may close these issues.

None yet

3 participants