vsch / laravel-translation-manager

Enhanced Management of Laravel 4 & 5 Translations, with Yandex Translation API assisted translations.
MIT License
181 stars 84 forks source link

how to access translations from javascript #112

Closed vesper8 closed 6 years ago

vesper8 commented 6 years ago

Hey, sorry if this is already documented but I wasn't able to locate the answer

I love your package and have been using it in my apps that use Laravel Blade

But now I am transitioning to using more and more Vue and I am finding myself needing to access these translated strings from inside the javascript

And I am wondering what is the optimal way of accessing what I need from a JS content. I am looking for a way that is not too hard on performance.. any advice would be much appreciated!

Thanks!

vsch commented 6 years ago

@vesper8, actually there is not an easy implementation at the moment.

I am sure it can be easily implemented by adding a JSON method to the translator web ui controller or to create a new controller to take in Laravel style translation keys and responding with the translations for these keys. This will allow getting translations in bulk instead of making a single request at a time.

Unfortunately at the moment I am swamped to implement this but will see if I can make time in the next few days to merge #110 and add this interface.

Since you are going to be using this do you have any preferences for the JSON protocol for this exchange?

vesper8 commented 6 years ago

Hello! Thanks so much for the super quick response!

I am still shocked that this repo has only ~100 stars! It should have thousands! I have tried a few other packages and yours has much better active development and complete functionalities.. and then there's this amazing support like in this issue!

Well to answer your question, I plan to use https://github.com/kazupon/vue-i18n which is by far the most popular localization package for Vue. It is able to handle some of the same features as your package.. but I prefer to use your package to manage all my translations and only use the vue-i18n package to load the json generated from your package and use it in the vue code

So basically.. I don't need anything special.. the vue-i18n package is capable of loading json files formatted like this:

en.json

{
  "test1": "English test 1",
  "test2": "English test 2"
}

So as long as you can export with this simple model then it should work fine!

Let me know if you have any other questions. Thanks!!

vsch commented 6 years ago

@vesper8, I think this would be addressed if the library implemented import/export of json style translations for Laravel. It could be the same issue as #104

I am going to make time to address. it has been outstanding for too long. I haven't used Laravel for a while and will need to brush up on the details of this feature.

vsch commented 6 years ago

@vesper8, thank you for the appreciation. For lack of library popularity I don't have an answer but suspect it has more to do with not caring enough about popularity to promote it.

vesper8 commented 6 years ago

hey @vsch

I could be missing something but it seems like this should be super easy to implement, considering that your package already outputs files which are almost exactly the format that is needed

For example, currently your package outputs

/resources/lang/en/locale.php

<?php

return [
    'en'    => 'English',
    'fr'    => 'Français',
];

All you would need to do is do the same thing but instead of writing a php array, you would wrap the php array with json_encode() and change the filename to json

and that would produce

/resources/lang/en/locale.json

{
  "en": "English,
  "fr": "Français"
}

And I could work with that. I actually prefer the ability to keep things separated in groups this way I can make a group which only contains translations that are needed in the javascript

vsch commented 6 years ago

@vesper8, the issue has never been generating or reading the files. That's a one liner, easier than PHP. The issue was the JSON keys which can be any old crap, of unlimited length, and not generally passable as a URL query param nor can be used in JavaScript for ID. Both of which are done in the code.

I implemented the changes by creating automatic old style translation keys for JSON imported files. These are put into the LTM table under JSON group. That is also where they show up in the Web UI. The mapping of LTM keys to JSON keys is stored in the LTM table under JSON group, json locale. That way import/export will correctly map JSON keys to translation keys and back.

On publish the JSON files are exported, and also a json.json file is output. This one saves JSON to LTM translation keys so that JSON keys could be efficiently converted to LTM keys for added functionality like usage tracking, missing key tracking and in database publishing for systems where translation files are read-only but there is a need to update translations.

For new keys, created in LTM, the JSON key will be taken from the translation value of the PRIMARY locale as configured in LTM config file. Failing that it will take the first translation value for any other locale.

I will push out a new version. Let me know what you find. I don't use Vue or javascript translations so don't have any real test cases to try.

vsch commented 6 years ago

@vesper8, its out. Please let me know if you encounter any issues.

PS. It was fun. I haven't worked in PHP or Laravel in almost two years. Took about 30 minutes to start remembering where things are but then it came back like I never stopped using it.

vesper8 commented 6 years ago

thank you so much for putting it out so quickly :)

I will be sure to let you know if I run into any problems using it.

I don't have time to implement it quite right away but will for sure be getting around to it within a few weeks tops

Glad you took pleasure in diving back into Laravel! Wow 2 years! Things have changed a bit since 5.2!

I wonder how you managed to make all those commits without ever needing to dive in!

vsch commented 6 years ago

@vesper8, most of the commits were either mechanical Laravel version necessitated changes for which I just followed the Laravel upgrade docs, or user submitted changes. I have been too busy to spend much time on this project beyond necessities.

As for the speed of this request, it was first requested in #104, last year so I cannot claim fast response on this. Your request showed why using this format was necessary. Since I did not follow the evolution of Laravel, I was not party to all the JavaScript integration.

No rush. I will be focusing on other work for a while and only addressing bugs that may come up.

vesper8 commented 6 years ago

Hey @vsch !

So I am finally getting around to using this!

I set up my vue-cli project to work with vue-i8ln and made it able to import files that look like this:

{
  "about" : "About"
}

Then I started populating my vue app with calls like these:

<span>{{ $t('about') }}</span>

Then I wanted to use pa translations:find to auto-populate the keys and here's when things got a little bit hairy

Well first of all I had to modify the vendor files because I could see no other way to make the translations:find command be modified for y needs

It would be nice if you could abstract

        $functions = array(
            'trans',
            'trans_choice',
            'noEditTrans',
            'ifEditTrans',
            'Lang::get',
            'Lang::choice',
            'Lang::trans',
            'Lang::transChoice',
            '@lang',
            '@choice',
            '__',
        );

and

        $pattern =                                  // See http://regexr.com/392hu
            "(" . implode('|', $functions) . ")" .  // Must start with one of the functions
            "\\(" .                                 // Match opening parentheses
            "(['\"])" .                             // Match " or '
            "(" .                                   // Start a new group to match:
            "[a-zA-Z0-9_-]+" .                  // Must start with group
            "([.][^\1)]+)+" .                   // Be followed by one or more items/keys
            ")" .                                   // Close group
            "['\"]" .                               // Closing quote
            "[\\),]";                               // Close parentheses or new parameter

and

$finder->in($path)->name('*.php')->name('*.twig')->files();

To the configuration file to allow for more flexibility

And it would be nice if there was a way to pass a path to the translations:find, but I saw that I could edit the paths inside the config/view.php file as an alternative, which is what I did

For now I changed the file to this:

        $functions = [
            '\$t',
        ];
        $pattern =                                  // See http://regexr.com/392hu
            '(' . implode('|', $functions) . ')' .  // Must start with one of the functions
            '\\(' .                                 // Match opening parentheses
            "(['\"])" .                             // Match " or '
            '(' .                                   // Start a new group to match:
            '[a-zA-Z0-9_-]+' .                  // Must start with group
            "([.][^\1)]+)+" .                   // Be followed by one or more items/keys
            ')' .                                   // Close group
            "['\"]" .                               // Closing quote
            '[\\),]';                               // Close parentheses or new parameter

        // Find all VUE files
        $paths = $path ? [$path] : array_merge([$this->app->basePath() . '/app'], $this->app['config']['view']['paths']);
        $keys = [];
        foreach ($paths as $path) {
            $finder = new Finder();
            $finder->in($path)->name('*.vue')->files();
            ...

Since this is what I need for my vue-cli app

I then ran pa translations:find and it found my keys

After a bit of trial and error I realized that in order to generate the json files, I need my keys to be in a JSON group (all caps). So I changed my keys inside my .vue files to:

<span>{{ $t('JSON.about') }}</span>

Which I found a bit redundant. I would have preferred to be able to use named groups so I could seperate my "nav" keys from my "article" keys. I kind of understand why you went through the extra trouble with how JSON keys are handled.. however I personally didn't need this and all my keys are going to be straightforward, short and not including any weirdness so what you did turns out to be an extra hurdle that wasn't really needed in my case at least.

After running it, this is what my fresh installation's ltm_translations table looks like: screenshot 2018-04-09 21 47 13

Then after adding the translations through your GUI interface for English and French it looks like this: screenshot 2018-04-09 21 47 40

And finally after hitting "publish all" or "publish group" it looks like this: screenshot 2018-04-09 21 48 13

And here's the content of the 3 files it published:

screenshot 2018-04-09 21 48 29

I only need the en.json and fr.json however. I guess you need the json.json internally

In any case, I don't know what I'm doing wrong, but it didn't set any key at all as you can see. Even though in the database it shows all 3 rows to have 'about' set as the key.

As far as I can undertstand form what you wrote

For new keys, created in LTM, the JSON key will be taken from the translation value of the PRIMARY locale as configured in LTM config file. Failing that it will take the first translation value for any other locale.

It should have defaulted to the key 'about' ? Is this a bug that I've run into? Having to set the key manually in the DB is going to be tedious for 100s of translations so I'll wait for your answer

Can you tell me, would it be simpler (the intended way) for me to create regular groups (not JSON) and then somehow export those to JSON ? It's not clear how I can do that.. I was looking for some kind of "Export to json" button but couldn't find one.

Also I guess this is a problem now because I need to add $t('JSON.mystring') or otherwise $t('mygroup.mystring') in order for translations:find to locate my keys, but when I export it to json those keys won't work. Easy to fix with a find/replace but still.. I think I am not getting the proper workflow to do this efficiently so maybe you can chime in and let me know your thoughts.

Many thanks for your continued hard work on this!

vsch commented 6 years ago

@vesper8, thank you for such detailed feedback. I will go through your information thoroughly, but after a quick run through I have the following comment:

The JSON group is only needed for the translation manager. The json translation file keys are just text used in the primary locale to create the entry. On the LTM side I generate automatic unique keys for LTM use, based on the non-ltm key. I save the original key in the json locale so that I can correctly generate the json translation files and in case of re-importing files will re-use the same key, otherwise the database will be messed up with multiple keys for the same json entry.

That is what the json.json file is for. It allows to keep track of previously generated keys that should be re-used. If you delete that file then all the keys will be re-generated.

The json translation files are generated so that in Laravel they can be used without specifying the group, at least as far as I could tell. These files are generated with their original keys.

  1. The vue t() requiring the group seems to be a requirement on the the vue side.

  2. Is there an option to set default namespace? Is it not using i18next module? It is used with react and has this option for default name-space. If you set it to JSON then you will not need to specify it for every translation. Option for i18next would be defaultNS: 'JSON', it will automatically use that if the key has no NS in it. The default NS for i18next is 'translations'

I am using LTM translations in React but opted out for downloading the translations myself since I am learning react and wanted to understand the lower level stuff so I can make LTM work better with it.

I needed to learn react for a project. Creating an app from scratch, to understand the nuts and bolts of it, was easier and faster than trying to figure things out from an existing 12MB react project.

The React UI for LTM will probably released within a day. I expect some issues since I haven't figured out all the laravel mix, babel presets and how to configure it for a vendor package sourced assets. I'll probably just make a prod version and copy the files from my public to ltm package public. The view file is already generic so it should work.

The source I will add to the package but it will need config changes if someone wants to develop with it. I had to get some hacks in so I can use the bootstrap-xedit control. Modules available for react are not fit to shine the boots of this barely supported and aging implementation. I could not see LTM without it.

Took some hacking but it works beautifully and the exercise forced me to understand react better.

I will go through the rest of your recommendations and don't see why they cannot be added to make life easier. It has been a long time since I used the find translations and I am sure "it could use a little attention".

vesper8 commented 6 years ago

Thanks for the explanations @vsch :)

No I'm not using i18next and I am lost as to what you mean about namespaces. I've also never used React but my understanding is that Vue is pretty similar. I'm not using any namespaces in the context of my translations inside my vue-cli app.

Just to be clear, my vue-cli front-end code is completely detached from my laravel backend, where LTM resides. They are not even in the same folder. As a result I also don't make use of Laravel Mix at all since I only use Laravel for the backend APIs. In order to have translations:find be able to search for keys inside my vue project I actually used a symlink since it's in another folder.

The reason I named my keys

<span>{{ $t('JSON.about') }}</span>

Is because translations.find has a regex requirement that all keys start with a group name. I could comment out those regex lines. But I also noticed that if the found keys are not part of the JSON group then there is no json files created when you publish.. instead it generates php files

The php files have proper keys, but the json ones do not as I detailed above.

I'm looking forward to your answers because I feel I may have encountered a bug or simply I am not understanding the correct workflow for using LTM exclusively for managing javascript translations

Thanks!

vsch commented 6 years ago

@vesper8, name-spaces in i18next terminology are groups in Laravel. Just a prefix separated from the key and you can configure how it is parsed. I suspect that there must be an option in vue for a default group.

The JSON files do not have proper keys because this is how Laravel expects it: https://laravel.com/docs/5.6/localization#using-translation-strings-as-keys

Can you make use of JSON translation files that you ajax from the server? The same way I am doing it for LTM react UI?

vsch commented 6 years ago

@vesper8, make the above JSON translations, not translation files.

vesper8 commented 6 years ago

I could potentially load the json files over ajax. However I have chosen to simply copy/rsync the compiled json files into my vue-cli app so that it can be included in the build bundle

also I'm not using json translations IN laravel.. in my particular case.. laravel is strictly an api and doesn't make use of any translations. I'm only using it to build the translation file themselves because I like using your package to do so

I'm sorry but I still don't understand how to use this. As you can see in my above screenshots, with the reproducible steps I've detailed, I end up with no keys for my translations which is not what I need.

If I manually set the value of the json locale row, only then are keys populated for my en.json and fr.json

Frankly I think there's a bug, I'm pretty sure that en.json and fr.json should never end up like they do in this screenshot

screenshot 2018-04-09 21 48 29
For new keys, created in LTM, the JSON key will be taken from the translation value of the PRIMARY locale as configured in LTM config file. Failing that it will take the first translation value for any other locale.

I don't think this is happening?

vsch commented 6 years ago

@vesper8, the key is taken from primary json file, which I assume is in your case is en. Laravel uses JSON files assuming that the key will be anything, but the default is that it is same as the primary translation. So that missing translations will return the key which is the default locale value.

You should have the en.json be:

{
     "About": "About"
}

fr.json

{
     "About": "À Propos"
}

Then your json.json will be:

{
     "About": "about"
}

The json.json converts the anything as key to LTM valid translation key.

Here is a set of small test files I use:

en.json:

{
    "a very long sentence for the key including some large % of ___nonaladf ja;lsdf fjas;lf jas;fl fl;jasf;ld l;j@@@J@$#$#%$#@#$@#$": "a very long sentence for the key including some large % of ___nonaladf ja;lsdf fjas;lf jas;fl fl;jasf;ld l;j@@@J@$#$#%$#@#$@#$",
    "a very long sentence for the key including some large % of ___nonaladf ": "a very long sentence for the key including some large % of ___nonaladf ",
    "new translation": "new translation",
    "new translation key": "new translation key",
    "test translation": "test translation",
    "un autre môt": "un autre môt",
    "новый ключ": "новый ключ"
}

fr.json

{
    "a very long sentence for the key including some large % of ___nonaladf ja;lsdf fjas;lf jas;fl fl;jasf;ld l;j@@@J@$#$#%$#@#$@#$": "une phrase très longue pour la clé, y compris certaines grandes % de ___nonaladf ja;lsdf fjas;lf jas;fl fl;jasf;ld l;j@@@J@$#$#%$#@#$@#$",
    "a very long sentence for the key including some large % of ___nonaladf ": "une phrase très longue pour la clé, y compris certaines grandes % de ___nonaladf",
    "new translation": "nouvelle traduction",
    "new translation key": "nouvelle traduction",
    "test translation": "traduction test",
    "un autre môt": "un autre môt",
    "новый ключ": "новый ключ"
}

json.json:

{
    "a very long sentence for the key including some large % of ___nonaladf ja;lsdf fjas;lf jas;fl fl;jasf;ld l;j@@@J@$#$#%$#@#$@#$": "a_very_long_sentence_for_the_key",
    "a very long sentence for the key including some large % of ___nonaladf ": "a_very_long_sentence_for_the_key_1",
    "new translation": "new_translation",
    "new translation key": "new_translation_key",
    "test translation": "test_translation",
    "un autre môt": "un_autre_môt",
    "новый ключ": "новый_ключ"
}
vsch commented 6 years ago

@vesper8, it sounds like you are not really using the JSON translations of Laravel so this is the reason why it does not work as you would expect.

The JSON translations for Laravel are really geared towards using the Laravel API, you are only copying them and trying to use them as regular i18n translation files.

In your use case json translation files should have normal translation keys, then LTM will generate identical keys and your whole json.json will have identity mapping. In this case you will have what you can use in JavaScript without issue.

Nothing in Laravel prevents you from doing this since there is no limitation on what can be a key in JSON.

vesper8 commented 6 years ago

This is getting complicated and I feel like we are not on the same page.

What I am looking for is something really simple.

Currently LTM is able to export a file such as

/lang/en/nav.php

<?php

return [
    'about' => 'About',
];

If the group is set to "nav"

ALL I'm really looking for is for a way to export that to

/lang/en.json

{
    "about": "About"
}

I'm beginning to think it may just be simpler to make a custom command that does this. But I thought this is what you had recently added, this is what I wanted all along

Currently the only way to achieve this is if my translations are part of a group called "JSON" in caps. And then this extra json locale row is created without a key and I need to add the key manually in the database otherwise it creates these files:

/lang/en.json

{
    "": "about"
}

/lang/json.json

{
    "": "about"
}

Now this doesn't look right at all to me.. how come neither of these files have a key!

Are you planning on adding/fixing it so that my straightforward use-case is able to be dealt with?

That would be fantastic

vsch commented 6 years ago

@vesper8, the blank key is a bug!.

I tried adding a new key to json translation files to match yours and it imports correctly and exports correctly.

It looks like your json.json file is out of sync with your translation files in the database and LTM failing to handle it properly.

  1. Publish your JSON translation group from LTM so you have all the translations
  2. Fix any keys that are blank in the JSON files so that these files are correct.
  3. Delete the JSON translation group in LTM and the json.json file.
  4. Import All with (Only add new translations) option so the JSON files get imported. The keys should be fixed.

If you modify the JSON files manually, you will need to delete the JSON translation group and json.json file and re-import the translations until I fix LTM to handle discrepancy between files being imported and the database so that it will not get out of sync.

Or for now modify JSON translations only in LTM.

vesper8 commented 6 years ago

In the meantime this SQL query does the job of filling out the missing keys

UPDATE ltm_translations SET value=`key` WHERE locale='JSON' AND value=''

The workflow is to

Publish All Run the mysql command Publish All

And then the en.json and fr.json are just what I need

vsch commented 6 years ago

@vesper8, yes this will fix the database corruption. I will need to fix the code to prevent it.

I think it happens if a key is added in LTM, which results in json locale to have empty translation which means the key is null. I will add code to set the json locale to the key when a key is created in LTM.

I will add this fix to the import and publish operations.

vsch commented 6 years ago

@vesper8, issue with JSON fixed. The cause was that I forgot to set the json locale keys when JSON group is being published. Until the group is published the keys remain empty.

React UI also released. It is the first incarnation but already quite good.

vesper8 commented 6 years ago

Thanks for the fix @vsch !

And the new react interface sounds very cool. I actually just spent the last 2 hours upgrading to Laravel 5.6 just so I could check it out, since it seems you only pushed the new react-ui to the 2.6 branch?

Anyway I was due to update.. ran into a lot of conflicts but I finally am back in a running state

However I'm running into a problem trying to access the new UI

I ran the new migration without a problem, but then when I try to access the /translations/ui route I get this error

Call to undefined function Vsch\TranslationManager\appDebug()
screenshot 2018-04-15 21 17 04

Can't find any function called "appDebug()" so I'm confused about this.. do you know why? Am I missing another step in my upgrade?

vsch commented 6 years ago

@vesper8, I made a new release without this function. It is simply a wrapper for Config::get('app.debug', false) for convenience with options to disable debug mode by using URL query params so I can test in a simulated prod environment. I replaced by config access.

vesper8 commented 6 years ago

Thanks for the fast response as usual @vsch

Almost there now.. but am running into another problem.. getting this error now

Undefined index: /vendor/laravel-translation-manager/css/index.css (View: /DEV/mydomain.com/vendor/vsch/laravel-translation-manager/resources/views/ui.blade.php)
screenshot 2018-04-15 22 20 01

I did publish the files and I do have a index.css located at /public/vendor/laravel-translation-manager/css/index.css which was put there by your publish command

Any idea what's missing now? I didn't run npm run dev/prod or anything like that or add anything to my local webpack.mix.js because that wasn't mentioned in the instructions. I think it may work on your machine because you've built the manifest.json by running the build command, but that manifest.json is missing for us

vsch commented 6 years ago

@vesper8, its the expected issues I was talking about. The manifest for mix is missing from public directory for mix to know how to map:

file name: mix-manifest.json

Contents:

{
    "/vendor/laravel-translation-manager/js/index.js": "/vendor/laravel-translation-manager/js/index.js",
    "/vendor/laravel-translation-manager/css/index.css": "/vendor/laravel-translation-manager/css/index.css",
}
vsch commented 6 years ago

@vesper8, actually you should add the above lines to your mix manifest. You already have the file but the entries are missing. I have to see how this can be done automatically since the manifest is overwritten every time you use mix to compile your assets.

vsch commented 6 years ago

@vesper8, remove the map entries, they're for dev.

I have to check laravel docs to see how to merge vendor mix manifest, otherwise the UI has to be built on each client. I don't think it is the latter. There has to be a way to tell in the webpack.mix.js that there are pre-built assets that need to be added to the manifest.

vsch commented 6 years ago

@vesper8, you can add the following lines to your webpack.mix.js to have LTM React files copied and added to the mix-manifest.json every time you compile your assets:

mix.combine(['vendor/laravel-translation-manager/public/js/index.js'], 'public/vendor/laravel-translation-manager/js/index.js')
    .combine(['vendor/laravel-translation-manager/public/css/index.css'], 'public/vendor/laravel-translation-manager/css/index.css')
;

I'll update installation procedure for the next release, which should be soon. I am re-working a few parts of the UI and adding better auto view update when server ops are performed.

vesper8 commented 6 years ago

sounds good, thanks!!

Ok I guess one last detail that I'm not getting, the react-ui is loading now, but the translation file for the UI itself doesn't seem to be loading.. I just see messages.xxx everywhere

I do have the /resources/lang/en/messages.php

am I supposed to do something so that this is converted to usable json by the interface itself?

vsch commented 6 years ago

@vesper8, my bad, they are taken from the database. I forgot that not everyone has the LTM translations managed.

I'll fix it. There is no quick fix for it in the config. It was a dumb oversight on my part and the group is hard-coded to my workbench import group. Even if you add the vendor package to importable files it will still be vnd: while the code looks for wbn:

Thank you for taking the time and sorry for the hassle. I will fix this and make a new release.

vsch commented 6 years ago

@vesper8, actually there is a quick fix. The config is flexible enough.

  1. In your LTM config, under language_dirs change the vendor entry to:
        'vendor' => [
            'include' => ['vsch/laravel-translation-manager'],
            'root' => '/vendor/{vendor}/{package}',
            'files' => 'resources/lang/{locale}/{group}',
        ],

        'vsch/laravel-translation-manager' => [
            '__merge' => ['workbench', 'vendor',],
            'db_group' => 'wbn:{vendor}.{package}::{group}',
        ],

Effectively, you are changing the vendor definition to include LTM and LTM definition to map its translations to wbn: prefixed instead of vnd:, LTM translations will show up as wbn:laravel-translation-manager.messages,

  1. Import all to import ltm messages and it will show the messages in the React GUI.

I am in the middle of some code changes and this is the quickest way to get around the issue.

vesper8 commented 6 years ago

Thanks for trying to get a quick-fix going.. but I can wait until your next release I think.

Anyway I did try your suggestions. First, the mix.combine is missing the 'vsch' in the path, so it should be like this:

mix.combine(['vendor/vsch/laravel-translation-manager/public/js/index.js'], 'public/vendor/laravel-translation-manager/js/index.js')
    .combine(['vendor/vsch/laravel-translation-manager/public/css/index.css'], 'public/vendor/laravel-translation-manager/css/index.css')
;

Then npm run dev works well and adds the files to the manifest.json

Just a note that it's not possible to run npm run prod because it complains about being unable to minify the index.js, it suggests using mix.babel instead and then complains about a missing transform-vue-jsx plugin

I then made the modifications to the config file and added the entries you noted above.

I then performed an 'import all'

And it added two new groups.

screenshot 2018-04-16 12 48 09

The 'vnd' group has all the entries populated, but the 'wbn' group has all the entries empty (no translations). As for the interface.. it still displays 'messages.xxx' everywhere

vsch commented 6 years ago

@vesper8, I will be making a release today with the fixes.

vsch commented 6 years ago

@vesper8, new version released. Now the React UI translations work like all other translations.

Added instructions to how to configure it for mix. use mix.copy instead of combine. https://github.com/vsch/laravel-translation-manager/wiki/React-App-UI

You should remove the config lines added for LTM translations and delete the group from the LTM database so it does not override the LTM package translations.

vesper8 commented 6 years ago

@vsch almost there now I can feel it!

What do you mean remove the config lines? you mean the ones you suggested earlier? I reverted to the package's configuration so I undid all those workaround fixes if that's what you meant

What do you mean remove the group from the LTM database?

I'm noticing now that if I truncate both the ltm_translations and ltm_user_locales table then the React UI loads fine with no errors in the console or under the Network tab

But if I leave my JSON translations in ltm_translations then everything blows up

The user-list, summary and trans-filters API endpoints all go red with errors

I thought the problem might be the json locale so I removed those rows.. but that doesn't fix the problem.

How can I keep using my hundreds of translations I had before? They are all under the JSON group

Lastly, the mix.copy trick works well, but using mix.react throws the same error as before with a missing plugin

vesper8 commented 6 years ago

I tried to start over to see where that would lead. I truncated both tables. Then I ran the pa translations:find command again, with my customizations from my PR

And it found 58 keys and added them to the table, under the group "JSON" since all my keys are named JSON.something

But now this group won't appear anywhere in the interface like it did before

Basically is there a new workflow for managing json translations now?

vsch commented 6 years ago

@vesper8, no new work flow. I try to keep that unchanging. It sounds like there is a bug. See below.

I use JSON in my test setup and not getting the exceptions but that is because my JSON content is contrived and does not represent what is possible. No truncation should be done or acceptable. It sounds like in my setup I am missing something that causes a bug in your setup.

Q: Can you make your JSON translations available so I can add them to my translations and have the same data. It also could be config

Reply to points raised in your comment:

  1. Yes

    What do you mean remove the config lines? you mean the ones you suggested earlier? I reverted to the package's configuration so I undid all those workaround fixes if that's what you meant

  2. You no longer need to have LTM translations in the database which was the reason for 1.

    What do you mean remove the group from the LTM database?

  3. You should not have to truncate your translations. I never clear my table, only run migrations. I have all the usage information in the tables which I don't want to loose.

    I'm noticing now that if I truncate both the ltm_translations and ltm_user_locales table then the React UI loads fine with no errors in the console or under the Network tab

    But if I leave my JSON translations in ltm_translations then everything blows up

    The user-list, summary and trans-filters API endpoints all go red with errors

    I thought the problem might be the json locale so I removed those rows.. but that doesn't fix the problem.

    How can I keep using my hundreds of translations I had before? They are all under the JSON group

  4. Lastly, the mix.copy trick works well, but using mix.react throws the same error as before with a missing plugin

    The copy should be done in your project's webpack.mix.js. You don't need to run the vsch/laravel-translation-manager webpack.mix.js

    The copy should just copy the compiled assets from the vendor directory. Are you getting these errors just by including the mix.copy lines to your webpack.mix.js?

vsch commented 6 years ago

@vesper8, what groups and locales do you have in your database?

JSON locales?

Non JSON locales?

I think it is a lack of data or something unexpected (not wrong, just not expected by the code) in the data that is causing the bug to be triggered.

vesper8 commented 6 years ago

I only touch my own webpack.mix.js not the vendor's one

mix.copy(...) works perfectly and that's all I need really.

I was just saying that adding mix.react(...) does however fail, because of a missing plugin

Here's a dump of my ltm_translations which is causing the issues

https://www.dropbox.com/s/m5lf7pawpbkgik8/vue-translations.sql?dl=1

vesper8 commented 6 years ago

The one above was my working one, already translated into french and with the json locale added

Here's the one that isn't causing errors, but where the JSON group just doesn't appear. This is after truncating the tables and running translations:find again

https://www.dropbox.com/s/ho55qz91qjugegv/vue-translations-untranslated.sql?dl=1

vsch commented 6 years ago

@vesper8, thank you for the files.

Yes, react will fail in your project because you don't have it configured for react preset. That is why my goal all along was to have the pre-compiled files from the vendor public folder be used for installation.

I'll take a look at the files now. Am I right to assume that these are the only translations in your table? If so then I will have nothing but these in my translation table to duplicate your environment.

vesper8 commented 6 years ago

yes those are the only translations I use in this project

vsch commented 6 years ago

@vesper8, I am able to duplicate a whole bunch of errors on my system. Thank you for the files. I'll have it fixed shortly.

vsch commented 6 years ago

@vesper8, fixed a couple of bugs that prevented display but not sure if this is what is causing issues on your system. It could be.

Your files helped me debug the show source feature. Mine don't have any sources so that feature was broken too.

Thank you very much for taking the time to help resolve these issues.

Please let me know if this version has any issues or whether the same problems persist.

If there are upgrade issues In the future, please let me know. You should not have to truncate any data to try and make LTM work. The upgrade procedure has to handle that.

vesper8 commented 6 years ago

no problem @vsch

Unfortunately I'm still having problems

So I just ran composer update and updated to 2.6.22

Then I restored my vue-translations.sql

So my ltm_translations has all my previously working translations and my ltm_user_locales is blank from being previously truncated)

I accessed /translations and there was simply no group.. I figured maybe this is a cache issue

So I clear my laravel cache.. and then try to access /translations again and this time I get the same error I've seen earlier

ErrorException: Undefined offset: 0 in file /DEV/_POC/new.classementpoc.com/vendor/vsch/laravel-translation-manager/src/Classes/TranslationLocales.php on line 80

From here.. if I truncate both tables.. clear cache/view/everything

I am still getting the above error.. can't access neither the old /translations or /translations/ui anymore

if I dd($userTranslatableLocales) on that line that's crashing I get

$userTranslatableLocales array (1)
⇄1 => string (2) "fr"

Maybe this is the part that I forgot to mention, which is that the only one change that I make to the default configuration file, besides adding my Yandex_key is that I add 'fr' to

    'locales' => [
        'en',
        'fr',
    ],

This seems to be causing these issues somehow? why? am I not supposed to do that? english and french are the two languages I care about and want to manage translations for

vesper8 commented 6 years ago

so for kicks I removed 'fr' from the locales in the config file (this is with my ltm_translations still blank) and then I was able to access the UIs

but then I restored my vue-translations.sql once again

And then I'm getting the error again

if I print out the array as above now I'm getting

$userTranslatableLocales array (2)
⇄1 => string (2) "fr"
⇄2 => string (4) "json"

This is with my configuration locales only containing 'en'

vsch commented 6 years ago

@vesper8, it definitely is an issue with the calculation of user translatable locales and display locales. I try to put the locales that are part of the working set at the head of the locale list.

I can see where the first exception is caused. I will load your tables and set the config locales to what you have. That way I will be able to duplicate your system. Once I can do that, fixing the bug is a cake walk.

vsch commented 6 years ago

@vesper8, locale only adds locales that you want to have even if there are not translations in the table for that locale. ie. it is a minimum list.

show_locales is a maximal list. Only locales from this list will be shown.

What is your primary locale, the one you work with as the source to translate? en I assume.

vsch commented 6 years ago

@vesper8, new version pushed. It was my mixing Java, JavaScript and PHP. In PHP array diff does an associative diff on the keys, even if it is an indexed arrays. So entry [0] may be removed and first element starts at [1].

Your config was necessary to have the issue arise.

I am leaving your translations until you confirm its working for you.