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] Crowdin Bridge: Fix locale vs LanguageId #50040

Merged
merged 1 commit into from
Apr 20, 2023

Conversation

pculka
Copy link

@pculka pculka commented Apr 17, 2023

Q A
Branch? 6.2
Bug fix? yes
New feature? no
Deprecations? no
Tickets Fix #...
License MIT
Doc PR symfony/symfony-docs#...

@carsonbot
Copy link

Hey!

To help keep things organized, we don't allow "Draft" pull requests. Could you please click the "ready for review" button or close this PR and open a new one when you are done?

Note that a pull request does not have to be "perfect" or "ready for merge" when you first open it. We just want it to be ready for a first review.

Cheers!

Carsonbot

@pculka pculka marked this pull request as ready for review April 17, 2023 13:17
@carsonbot carsonbot added this to the 6.2 milestone Apr 17, 2023
@@ -109,6 +109,25 @@ public function read(array $domains, array $locales): TranslatorBag
$translatorBag = new TranslatorBag();
$responses = [];

$localeLanguageMap = [];
foreach ($this->listLanguages($locales) as $language) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this method doesn't accept any arguments

Copy link
Contributor

Choose a reason for hiding this comment

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

Probably it would be better to extract this to a separate method, e.g. mapLocaleToLanguageId or something like this

@@ -118,7 +137,7 @@ public function read(array $domains, array $locales): TranslatorBag

foreach ($locales as $locale) {
if ($locale !== $this->defaultLocale) {
$response = $this->exportProjectTranslations($locale, $fileId);
$response = $this->exportProjectTranslations($localeLanguageMap[$locale], $fileId);
Copy link
Contributor

Choose a reason for hiding this comment

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

The same issue probably is also relevant for the uploadTranslations method

Copy link
Author

Choose a reason for hiding this comment

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

Actually from my observation the mapping is done on Crowdin side and works (i.e. de-DE source gets properly mapped to de)

@andrii-bodnar
Copy link
Contributor

Hi @pculka, could you please provide locale examples than currently can't be synced with Crowdin?

@andrii-bodnar
Copy link
Contributor

The failed Unit tests do not expect the GET languages call, you should include the mock for this call in the tests

@pculka
Copy link
Author

pculka commented Apr 18, 2023

Hi @andrii-bodnar - In our project we use full locale codes, not language codes. For example for Germany the full locale is de-DE. This is in languages endpoint of Crowdin is stated as locale attribute:

"data": {
  "id": "de",
  "name": "German",
  "editorCode": "de",
  "twoLettersCode": "de",
  "threeLettersCode": "deu",
  "locale": "de-DE",
  "androidCode": "de-rDE",
  "osxCode": "de.lproj",
  "osxLocale": "de",
  "pluralCategoryNames": [
      "one",
      "other"
  ],
  "pluralRules": "(n != 1)",
  "pluralExamples": [
      "1",
      "0, 2-999; 1.2, 2.07..."
  ],
  "textDirection": "ltr",
  "dialectOf": null
}

When downloading translations in your code - you also properly annotated that the requested parameter has to be LanguageID, but you pass in locale and that fails. If I pass locale, I have to find the correct language ID by the locale and then the languages will be downloaded.

@pculka
Copy link
Author

pculka commented Apr 18, 2023

I'll try to add GET for the mock

@andrii-bodnar
Copy link
Contributor

@pculka got it, the current approach might be unreliable since a user can use a different language code format and in this case it's hard to guess the right language ID. I would suggest encouraging users to use Language Mapping in this case.

The flow:

  • a user has some locale that is different from the default Crowdin language ID
  • a user set up the Language mapping for this locale in the Crowdin project
  • then, on the Provider side you can use the Get Project to get the languageMapping property and find the language ID for the mapped locale.
  • use this language ID for requests.

This will not break any existing integrations and will allow customizing the used language codes.

By the way, something similar is suggested for the other translation provider here - https://symfony.com/doc/current/translation.html#installing-and-configuring-a-third-party-provider

@pculka
Copy link
Author

pculka commented Apr 18, 2023

Well I think the core problem lies in misunderstanding and misdocumentation of how to use locales should be used within symfony itself. It tends to be easy to confuse code vs locale vs osxlocale, etc. That's why I ended up here, as I was using proper i18n locale string, but in communication with CrowdIn the expected parameters are Language IDs.
Hence in your suggestion you suggest MIX UP between locale and language id once again. I mean - it is doable, but not sure if that's the right thing to do.

Anyway I've added the mapping, in get project info I now have:

        "languageMapping": {
            "de": {
                "locale": "de-DE"
            },
            "hu": {
                "locale": "hu-HU"
            }
        },

You suggest I change this code I provided to check for the project languageMapping setting and just fix it that way, right?

@andrii-bodnar
Copy link
Contributor

@pculka does Symfony has some language codes list that is recommended to use for translation catalogs?

@pculka
Copy link
Author

pculka commented Apr 18, 2023

I doubt it. both 'de' and 'de-DE' are valid locale strings, both referencing german language, but -DE specifies also the region which is optional. I mean. Meaning de-DE should try automatically a fallback maybe? Not sure how to tackle this situation properly.

@andrii-bodnar
Copy link
Contributor

Well, the Language Mapping approach might be more complicated. Probably we can keep the suggested approach in this case and not overcomplicate this for now

@pculka
Copy link
Author

pculka commented Apr 19, 2023

added one more fallback for underscore locale (you had that in one of your tests), and tests are passing.
Hopefully someone merges this

@pculka
Copy link
Author

pculka commented Apr 19, 2023

and refactored - extracted the mapping function out

@pculka
Copy link
Author

pculka commented Apr 20, 2023

@nicolas-grekas please can you check this PR? I also noticed a failed test in appveyor, 1) Symfony\Component\Messenger\Bridge\Redis\Tests\Transport\RedisExtIntegrationTest::testGetAfterReject

something in terms of redis. Maybe there is a problem with redis.dll for windows, which is not compiled for 8.2 - If it is needed, I compiled a working redis.dll for 8.2.5 for x64 both ts and nts versions: https://github.com/pculka/phpredis/releases/tag/5.3.7

But if it is possible to merge without passing appveyor, it would be great to get this done (and if @andrii-bodnar agrees)

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

I'm going to trust you on this one :)

@nicolas-grekas
Copy link
Member

Thank you @pculka.

@nicolas-grekas nicolas-grekas merged commit 5269b70 into symfony:6.2 Apr 20, 2023
7 checks passed
@fabpot fabpot mentioned this pull request Apr 28, 2023
nicolas-grekas added a commit that referenced this pull request Dec 26, 2023
…i-bodnar)

This PR was submitted for the 6.4 branch but it was merged into the 6.3 branch instead.

Discussion
----------

[Translation][Crowdin] Use project language mapping

| Q             | A
| ------------- | ---
| Branch?       | 6.3
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Issues        | -
| License       | MIT

Sometimes the locale codes may be different from the [codes](https://developer.crowdin.com/language-codes/) used in the Crowdin API. This will cause API errors because the wrong code is passed in the upload and download translation requests. There was already a fix (#50040), but it only works partially.

The suggested approach uses the [language mapping](https://support.crowdin.com/project-settings/#languages) configured in the Crowdin project. If the locale code and the crowdin code are different, the user needs to configure the language mapping in the Crowdin project.

Documentation - symfony/symfony-docs#19325

Commits
-------

a1d2f67 [Translation] Crowdin Bridge: use the project language mapping
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.

None yet

4 participants