8000 [Translation] Prevent creating empty keys when key ends with a period by javleds · Pull Request #52005 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Translation] Prevent creating empty keys when key ends with a period #52005

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

Merged

Conversation

javleds
Copy link
Contributor
@javleds javleds commented Oct 12, 2023
Q A
Branch? 5.4
Bug fix? yes
New feature? no
Deprecations? no
Tickets Fix #51536
License MIT

Small fix that prevents creating empty keys on translations when the translation key ends with a period, example:

'This is a validation.'

Before the fix, the yaml output was:

'This is a validation':
         '': 'This is a validation.'

After the fix we got:

'This is a validation.': 'This is a validation.'

This can be replicated by:

  1. Create a new symfony project using the --webapp flag.
  2. Execute the command to extract translations as yaml: php bin/console translation:extract --force --format=yaml --as-tree=3 --prefix='' --clean en

Results:
Before the fix:
image

After the fix:
image

@carsonbot
Copy link

Hey!

I see that this is your first PR. That is great! Welcome!

Symfony has a contribution guide which I suggest you to read.

In short:

  • Always add tests
  • Keep backward compatibility (see https://symfony.com/bc).
  • Bug fixes must be submitted against the lowest maintained branch where they apply (see https://symfony.com/releases)
  • Features and deprecations must be submitted against the 6.4 branch.

Review the GitHub status checks of your pull request and try to solve the reported issues. If some tests are failing, try to see if they are failing because of this change.

When two Symfony core team members approve this change, it will be merged and you will become an official Symfony contributor!
If this PR is merged in a lower version branch, it will be merged up to all maintained branches within a few days.

I am going to sit back now and wait for the reviews.

Cheers!

Carsonbot

@carsonbot
Copy link

Hey!

Thanks for your PR. You are targeting branch "6.4" but it seems your PR description refers to branch "5.4 for bug fixes".
Could you update the PR description or change target branch? This helps core maintainers a lot.

Cheers!

Carsonbot

@javleds javleds changed the base branch from 6.4 to 5.4 October 12, 2023 03:36
@javleds javleds force-pushed the ticket_51536_fix_empty_yam_tranlation_keys branch from e3a062a to 1d41e2c Compare October 12, 2023 03:45
@carsonbot carsonbot changed the title Prevent creating empty keys when key ends with a period [Translation] Prevent creating empty keys when key ends with a period Oct 12, 2023
@OskarStark OskarStark modified the milestones: 6.4, 5.4 Oct 12, 2023
@javleds javleds force-pushed the ticket_51536_fix_empty_yam_tranlation_keys branch 4 times, most recently from fb42f23 to 57ce1f4 Compare October 13, 2023 00:27
@@ -96,4 +97,45 @@ private static function cancelExpand(array &$tree, string $prefix, array $node)
}
}
}

private static function getKeyParts(string $key)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can simplify this method with something like:

function getKeyParts(string $key) {
    $parts = explode('.', $key);
    $nb = count($parts);

    if (str_starts_with($key, '.')) {
        $parts[0] = '.';
    }
    if (str_ends_with($key, '.')) {
        $parts[$nb-1] = '.';
    }
    return $parts;
}

Copy link
Contributor Author
@javleds javleds Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @welcoMattic. I love short code...

Nevertheless the shared code has 2 small disadvantages:

  1. It is using functions available from php 8.0^ (str_starts_with and, str_ends_with), this code is intended to be part of the version 5.4 which still supports older versions of php.
  2. Even if this covers the main goal (which is prevent empty keys with dots at the begining and, in the end) this is not covering some edge cases:
'abc 1.abc 2' => 'value',
'bcd 1.bcd 2.' => 'value',
'.cde 1.cde 2.' => 'value',
'.def 1.def 2' => 'value',

Please see the test of this section for more info.

If I am not addressing something, please let me know, I will be glad to adjust the PR if needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for php version, you can leverage symfony/polyfill-php (find the one v that introduced the relevant function)

Copy link
Contributor
@squrious squrious Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The polyfill that introduces str_starts_with and str_ends_with is symfony/polyfill-php80, and it is already required in the Translation component so using those functions is ok imo

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ho indeed cool if already included

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@javleds It seems the edge cases you mention are covered by simplier code here:
https://3v4l.org/2ic9k

function getKeyParts(string $key) {
    $parts = explode('.', $key);
    $nb = count($parts);

    if (str_starts_with($key, '.')) {
        $parts[0] = '.';
    }
    if (str_ends_with($key, '.')) {
        $parts[$nb-1] = '.';
    }
    return $parts;
}


var_dump(getKeyParts('abc 1.abc 2'));
var_dump(getKeyParts('bcd 1.bcd 2.'));
var_dump(getKeyParts('.cde 1.cde 2.'));
var_dump(getKeyParts('.def 1.def 2'));

Copy link
Contributor Author
@javleds javleds Oct 13, 2023
8000

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the advise of php polyfill, I will keep in mind in the case we need to perform additional updates. 🙏

Getting back to the code discussion:

The real problem here is to avoid trimming the periods at the beginning/end of the parts. Since the getElementByPath function is itended to process each part as a valid string. Having empty positions or a position wihtn a single dot won't give the expected result.

For example:

  • ['foo', 'bar'] will give the expected result.
  • ['foo', '', 'bar'] won't give the expected result due the empty position.
  • ['foo', 'bar', '.'] won't give the expected result due the period at position 2.
  • ['.foo', 'bar.'] will give the expected result.

The simpler solution is to keep the period concatenated to the key part, and prevent the period occupate a single possition in the array. Otherwise, we will have to add extra processing inside the getElementByPath function.

Having this in mind, the code proposed above has small variations on the expected result.

Let me give the examples:

input expected output with current fix output with simpler code
abc.abc ['abc', 'abc'] ['abc', 'abc'] ['abc', 'abc']
bcd.bcd. ['bcd', 'bcd.'] ['bcd', 'bcd.'] ['bcd', 'bcd', '.']
.cde.cde. ['.cde', 'cde.'] ['.cde', 'cde.'] ['.', 'cde', 'cde', '.']
.def.def ['.def', 'def'] ['.def', 'def'] ['.','def', 'def']

If the proposed solution is hard to read, maybe, we can create named variables for every if statement.

// input
[
'foo.' => 'foo.',
'bar.' => 'bar.',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'bar.' => 'bar.',
'.bar' => '.bar',

As you already test trailing period in 1 word-key on the previous line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right.

Both cases were intended to test no affectation with or without blank spaces, but, since the spaces are no affecting the output we will simplify reading by removing those (we can remove 2 entries lines 77 and, 78).

Next update will contain this cahnges.

[Translation] create getKeyParts() to keep periods at start or end of the key

[Translation] Simplify test cases by removing blank spaces
@javleds javleds force-pushed the ticket_51536_fix_empty_yam_tranlation_keys branch from 57ce1f4 to 5b0cf25 Compare October 13, 2023 14:41
@nicolas-grekas
Copy link
Member

Thank you @javleds.

@nicolas-grekas nicolas-grekas merged commit 4825733 into symfony:5.4 Oct 13, 2023
@fabpot fabpot mentioned this pull request Oct 21, 2023
@fabpot fabpot mentioned this pull request Oct 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Translation] extract-option 'as-tree' creates empty property keys in Yaml
8 participants
0