Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork9.7k
[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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
[Translation] Prevent creating empty keys when key ends with a period#52005
Uh oh!
There was an error while loading.Please reload this page.
Conversation
carsonbot commentedOct 12, 2023
Hey! I see that this is your first PR. That is great! Welcome! Symfony has acontribution guide which I suggest you to read. In short:
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! I am going to sit back now and wait for the reviews. Cheers! Carsonbot |
carsonbot commentedOct 12, 2023
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". Cheers! Carsonbot |
e3a062a to1d41e2cComparesrc/Symfony/Component/Translation/Tests/Util/ArrayConverterTest.php OutdatedShow resolvedHide resolved
Uh oh!
There was an error while loading.Please reload this page.
fb42f23 to57ce1f4Compare| } | ||
| } | ||
| privatestaticfunctiongetKeyParts(string$key) |
There was a problem hiding this comment.
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;}There was a problem hiding this comment.
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:
- 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.
- 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 seethe 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.
There was a problem hiding this comment.
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 leveragesymfony/polyfill-php (find the one v that introduced the relevant function)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
The polyfill that introducesstr_starts_with andstr_ends_with issymfony/polyfill-php80, and it isalready required in the Translation component so using those functions is ok imo
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
functiongetKeyParts(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'));
There was a problem hiding this comment.
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 thegetElementByPath 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 thegetElementByPath 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 everyif statement.
| // input | ||
| [ | ||
| 'foo.' =>'foo.', | ||
| 'bar.' =>'bar.', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
| 'bar.' => 'bar.', | |
| '.bar' =>'.bar', |
As you already test trailing period in 1 word-key on the previous line
There was a problem hiding this comment.
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
57ce1f4 to5b0cf25Comparenicolas-grekas commentedOct 13, 2023
Thank you@javleds. |
Uh oh!
There was an error while loading.Please reload this page.
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:
After the fix we got:
This can be replicated by:
--webappflag.php bin/console translation:extract --force --format=yaml --as-tree=3 --prefix='' --clean enResults:

Before the fix:
After the fix:
