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

Auto translate using Translation Engine #284

Open
wants to merge 17 commits into
base: 2.x
Choose a base branch
from

Conversation

timoye
Copy link

@timoye timoye commented Aug 26, 2023

translation:auto-translate
This command will scan your project (using the paths supplied in the configuration file) and create all of the missing translation keys. This can be run for all languages or a single language.

It will then translate all the tokens using Google Translate for FREE!

You can edit these auto translated texts using the User interface

Copy link

@q-- q-- left a comment

Choose a reason for hiding this comment

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

Hi,

I tested this pull request as we're looking into using this for our own project.

Summary

It works mostly fine, but it has trouble with

  1. translating texts where the key is different from the associated English text, as it translates the key instead of the value
  2. Single quotes inside calls to __(): __('Don't mess up my translation') becomes Don\\'t mess up my translation instead of Don't mess up my translation

as well as some smaller issues.

Longer version

How did I test the package?

  1. Install the timoye/laravel-translation auto-translate branch with Composer.
  2. Create a language with missing translations.
  3. Run php artisan translation:auto-translate [languageCode] and check if it captures all keys.

How did I compare translations?

  1. Sort both en.json and <new language>.json using a tool like JSON sorter.
  2. Paste both in DiffNow or a similar tool and check for new or deleted lines and how it translates each line.

Note
I did not compare the lang/<languageCode>/<...>.php files.

Results

Neutral

  • It skips keys in en.json that are not used in the code. This is because it uses the translatable texts from the source code instead of from en.json!

Buggy or problematic for my use case

  • Instead of translating the value in en.json, it translates the key from the source code. This causes issues if the key is not equal to the translatable text!

Example of the app translating the key instead of the value

  • Calls to __() with PHP code inside are not recognized (and therefore skipped); for example (changed up a bit to remove project details):
__('The user :user has been updated', ['user' => $user->name]), __($user->gender == 'female' ? 'Please take a look at her profile.' : 'Please take a look at his profile.', ['user' => e($user->name)]), __('Proceed to profile page'), subroute('profile.index'));

This is the only one I found in my project, so it's not the most pressing issue.

  • Unlike the other package I tried using, it does not completely ignore texts with quotes. However, because it extracts them from the source code, quotes are double-escaped: __('Don\'t mess up my translation') becomes the key Don\\'t mess up my translation, instead of Don't mess up my translation (backslashes are not needed here, as JSON uses double quotes instead of single quotes).

Good

  • Texts with newlines in the key and/or value, for example, "Preferably, as long as there are mentors of the same\n gender available": "Preferably, as long as there are mentors of the same\n gender available", are handled correctly (unlike tanmuhittin/laravel-google-translate). Although in my translation, it uses \r\n in the key (and \n in the translation). This may be Windows-specific.
  • Texts with double quotes in the key/value are handled correctly (unlike the other package I tried using):
    "You are not allowed to send a message to the user with user id \":id\".": "You are not allowed to send a message to the user with user id \":id\".",
    becomes
    "You are not allowed to send a message to the user with user id \":id\".": "Non è consentito inviare un messaggio all'utente con ID utente \":id\".",

Note
I only checked the JSON; files in lang/<languageCode>/*.php have not been checked.

foreach ($groups as $group => $translations) {
foreach ($translations as $key => $value) {
if (in_array($value,["",null])){
$new_value=$this->getGoogleTranslate($language,$key);
Copy link

@q-- q-- Feb 1, 2024

Choose a reason for hiding this comment

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

W.r.t. the issue I identified earlier,

Instead of translating the value in en.json, it translates the key from the source code. This causes issues if the key is not equal to the translatable text!

I fixed this function to pass the value from the source language instead:

    /**
     * Loop through all the keys and get translated text from Google Translate
     *
     * @param $language
     */
    public function translateLanguage($language){
        $translations = $this->getSourceLanguageTranslationsWith($language);

        foreach ($translations as $type => $groups) {
            foreach ($groups as $group => $translations) {
                foreach ($translations as $key => $value) {
                    $sourceLanguageValue = $value[$this->sourceLanguage];
                    $targetLanguageValue = $value[$language];
                    
                    if (in_array($targetLanguageValue,["",null])){
                        $new_value=$this->getGoogleTranslate($language,$sourceLanguageValue);
                        if (Str::contains($group, 'single')) {
                            $this->addSingleTranslation($language, $group, $key,$new_value);
                        } else {
                            $this->addGroupTranslation($language, $group, $key,$new_value);
                        }
                    }

                }
            }
        }
    }

It now works correctly

Copy link

Choose a reason for hiding this comment

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

I've created a pull request for your auto-translate branch to fix this, please check it out!

timoye#1

q-- and others added 2 commits February 8, 2024 16:16
This resolves the issue where, instead of translating the value in the
language file of the source language (e.g. en.json), it translates the
key from the source code. This causes issues if the key is not equal to
the translatable text!
…tion

auto-translate value instead of key
@timoye
Copy link
Author

timoye commented Feb 9, 2024

I have merged the PR timoye#1 from @q--

q-- and others added 7 commits February 27, 2024 16:09
Instead of defaulting to 'auto' and relying on Google guessing this
correctly.
getSourceLanguageTranslationsWith() only takes strings from the language
files, not from the application source code.

If you call auto-translate with a language parameter, it'll add missing
keys to the target language, but not to the source language files.

We work around this by falling back to the key if no value is set in the
source language.
…_empty_-_using_auto_translate_branch_as_a_base

Fall back to key if source language is empty
@@ -78,7 +78,7 @@ public function autoTranslate($language = false)
* @throws \ErrorException
*/
public function getGoogleTranslate($language,$token){
$tr = new GoogleTranslate($language, $this->sourceLanguage);
$tr = new GoogleTranslate($language);
Copy link

Choose a reason for hiding this comment

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

It isn't strictly necessary to pass the source language, but it's my understanding that if you don't, Google Translate will try to guess the source language (it's set to auto). That can sometimes lead to wrong results if two languages have the same word with a different meaning, e.g. the word 'brand' means fire in Dutch.

Copy link
Author

Choose a reason for hiding this comment

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

oh I see. that is correct.
I didn't look at that.

Copy link

Choose a reason for hiding this comment

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

No problem. Thanks for your part of writing this pull request

Copy link
Author

Choose a reason for hiding this comment

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

It is my pleasure.
It was quite helpful to me and I thought to let others use it also

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.

2 participants