What about translatable fields?
In my own project I use https://github.com/spatie/laravel-translatable and create new field with tabs for each language.
Yup, that's exactly the plan :-) And that's exactly the package I was planning on using. Also, I plan on the Edit button having a dropdown with all the languages so you can go directly to it.
Haven't had time to do the multilanguage functionality yet, but I will soon, 'cause it's an important feature.
Oh, sorry. In fact, I haven't made up my mind yet wether to use:
The important difference being if it's better to store the translations in a separate table, or in a JSON field in the same table.
What's your opinion about this?
I liked the idea with JSON fields, MySQL already have this feature. We need less time for configuration (no need to create additional models, migrations) and the package from dimsav there are bugs that are already for a long time are not fixed.
So i finalize my own translatable fields and it looks like:

I like it! Let's make some improvements on it for the general implementation, from a UX standpoint.
I've had this problem in the past with clients translating websites and their approach to translation is usually different. In your interface the best way to translate is:
But their approach was closer to:
This might totally work for your project (I don't know anything about it), but I think for the general implementation we should do something close to this:

Which (I believe) has a few benefits:
I am, however, struggling with:
TECHNICAL:
1) whether to place translations in JSON or a separate table (as discussed above);
Will follow-up with a comprehensive comparison for us to make a decision. There are a lot of factors to be taken into consideration here, including:
UI:
2) whether to place the big tabs at the top of the form, or use bootstrap pills on the left side of the form, in order to:
Need to see how that would look, though, might be pretty ugly and/or confusing (we already have the left-side menu).
UX:
3) whether the big tabs/pills should function as:
Do users actually insert a row already translated, or do they translate it after the fact? My gut tells me they don't, but we need to do some user research to find out.
In my previous admin panel builder (Dick), I did implement translatable fields, but I made the mistake of implementing the first solution that came to mind. Then wanted to change a lot of stuff, but I couldn't, because people were already using the package the way I built it. I don't want to make that same mistake again. I'm hopefully not going to fall into analysis paralysis, but this is a complex functionality that I want to get right from the start. That's the entire reason we don't have it by now :-)
What are your thoughts on the 3 issues above?
Technical issue
Saving the language in a separate table will give an advantage in speed, because there is no need each time to parse json (except mysql 5.7 and above), but as a consequence, a long initial setup.
UI
In my previous implementation of multi-language site I just did as you have in the screenshot, but there were not as such the possibility to dynamically add fields.
Based on the foregoing, we conclude that the best thing will be to implement a separate table for languages.
Or add the locale as a column for the table that becomes translatable and using a global query scope for filtering?
@axyr that's exactly what the dimsav/laravel-translatable package does.
@tabacitu I begin to rewrite the multilingual field tomorrow, but it will no longer field would be correct to call it a multilingual CRUD, see what happens. For me, this is the first experience of participation in the open sourse community. Inspiring
IMO I prefer the separate table approach and beside your points I think that the majority of hosting companies have not switched to MySQL v 5.7 at least in my country.
Maybe tabs with a bit of add-on solution like this for example or this
Separate pages I guess... would not it be easier when validating the request or response back with error messages (except If we use some ajax requests).
Note sure the progression of this item, or if this has been started/finished or whats not, but we had a think about this in the past and we ended up choosing to do it was something like:
$row->id = 1;
$row->name = 'over';
$row->description = 'its over';
$row->status = 1;
$row->translations = {}; //json store of translations
then the translations column would be a json store of the customised fields so you'd have
{
"de" : {
"name": "uber"
}
}
then something like which updates the actual values
if( $session->locale !== 'en' ){
$row = array_merge($row, $row->translations->{$session->locale})
}
and you end up something like
$row->id = 1;
$row->name = 'uber';
$row->description = 'its over';
$row->status = 1;
$row->translations = {}; //json store of translations
We chose this route as the previous translations table we had got incredibly large and became a nightmare to debug and trace back data as you never knew if if the data was in the translations table or the actual models database row
@OwenMelbz ,
That actually makes more sense to me than:
OR
Do you know any package that does that for Laravel, so we just create the interface for it, or would we have to code the translation storage/retrieval logic too?
@tabacitu I've never seen it done in laravel, however I know https://wpml.org/ for wordpress does it with serialised data.
So potentially this might be something needing to be built from scratch, so in the long run maybe worth using a pre-existing library than supporting another package/section.
One of the biggest issues I can see being tricky in laravel would be things like
Trains::where(['url' => Request::segment(1)]->get(); as the segment would be in German, but the Model will run the search on the url field, not the json field.
A problem I see with this design is that what happens when you have a field that is not translatable and is the same for both languages. For instance a color or time field. All of the translation wordpress plugins I've seen have a tab per field for this reason.
Hmm... I think you're right, @VictorSigma . There definitely should be non-translatable columns. That's easy to do in code, with a property on the model (dimsav/translatable has $translatableAttributes and spatie/translatable has $translatable).
But how would this be reflected in the interface? I see three options:
1) We show the untranslatable fields in all translations, so you can edit them from anywhere; we also show some sort of notice next to each untranslatable field, to let the admin know that value will be updated across all translations;
2) We show the untranslatable fields only in the primary form, and maybe show them disabled in all others, with a notice "modify this from the primary form".
3) We show the untranslatable fields separately;
I think the most user-friendly option is the first one, since it doesn't require the user to go somewhere else, modify it, then come back. And it doesn't require him to complete 2 tabs in order to submit one entity (translatable and untranslatable fields).
What do you think?
@OwenMelbz you're going to love the MySQL JSON columns ;-)
However, we should keep PostgreSQL, SQL Server, SQLite, MongoDB support in mind...
Honestly I don't really like any of those options. And much prefer the tab per field. When translator translates a piece of text or if the person is already multi-lingual, they will need to quickly jump back and forth between the language fields (especially if their is a long piece of text). In the "tab per language scenario" the translator will need to scroll down read a sentence, scroll back up, switch tabs, scroll back down, write the translation. Repeated for every single sentence/field. Constantly scrolling back up and down. I know it doesn't look as clean but it is the way most sites I've seen do it.
@VictorSigma , I think you're right, that would be way too much jumping around. That's why I proposed that the default value when you're on a translation page to be the text in the "primary" language (see image again). So the translator wouldn't have to jump at all: if you have English (primary), French and German, when on the French tab you'd already have the English texts typed in. You'd only need to write your French text in the field and then delete the English one. That would make translating to a new language almost twice as fast, I believe. I think it's the fastest for the translator, because:
Please tell me if having the primary language pre-written makes this a better option than tabs in your opinion.
I do see a possible problem with this interface though: if the admin clicks "save" after translating just a few fields, the translations would be saved (French text), though the text is actually in English (following the same example). But I guess we can solve that with a big NOTICE. Right?
Cheers and thanks!
I do see a possible problem with this interface though: if the admin clicks "save" after translating just a few fields, the translations would be saved (French text), though the text is actually in English
I don't see this as a problem since most systems I saw will fallback to the English if no translations exists. Although you might want to make this an option. I see it more of a storage issue. Say I have a news site with articles. Maybe only a 1/6 of them will have a translations out of the thousands. But every article will have two copies of the exact same text stored in the DB. This might be mitigated with some code checking for duplicates. But then the View might want to check if there is a translation available and then it becomes unclear. Some languages use a mixture of english and another language such as hindi. In that case the english and hindi translation might be the same thing.
I do like the like the copying of formatted text between languages and see how it mitigates a lot of the problems. I could see this being done when the user switches tabs. I still like the need to flip back is important for each field. Sometime translations are not easily one to one. For instance I've had clients completely reorder a piece of text essentially destroying the original. Plus their is the use case of a bilingual person writing something then immediately writing the translation (this is done a lot for short fields). How bout something like

? Seems like it has a lot less clutter and takes up the same amount of space whether the user is using translations or not.
Something useful to think about :) https://cwhite.me/translating-eloquent-fields-with-mysqls-native-json-type/
Hi! Is there any update on this issue? Thanks
I HOPE to have this finished by the end of the month. It's the next feature to be launched, and it's an important one. Hope I can make the time to do it. I'll keep you guys updated.
Cheers!
Great news, I will stay tunned. Thank You! :)
+1 for separate table to allow compatibility with existing systems. Including Asgardcms and other projects we have with dimsav/laravel-translatable
UI/UX
This is how a plugin of OctoberCMS is doing it, with a dropdown per-field basis

I believe this solution is the most elegant and doesn't add tabs that can get confusing/clunky quickly
Some improvements I would add from the above solution
something like this

And as a nice to have I would also add a visual feedback about the state of the translation for each locale
The indicator (kind of ugly in the mockup :) could be both at the locale and field level
It would assist the editor when uploading/reviewing translations

Wow, that erm, I do not like that at all haha! Imagine being a dutch editor, then having to click on every dropdown field to reveal the language you want, or conflicts with other field types that have inline interactions. Personally I think that wont work for Backpack unless I'm overlooking something.
My personal preference has always just been a simple query string and dropdown which lets you pick the language you're editing. Then the UI would be as simple as a dropdown you pick which version you're currently editing

@OwenMelbz that could work too :)
IMO to the solution you proposed we still need a to add an indicator of which fields are global and which are translatable (inline with the label?)
Ah I see yeah, I just assumed then that all fields are translatable :P but sure a little visual indicator by the labels would definitely be helpful
Base/Crud have had the philosophy of not forcing any certain type of experience on the end user. I do like the feature and think it's neat, but adding it sets a precedent thatBase/Crud are now both okay with being opinionated.
I personally like leaving stuff like this optional as a separate package.
Hmm... I'd have to agree with @OwenMelbz on this one. The dropdown he's proposed is a ridiculously simple solution for a complex problem. And I love it when that happens :-)
@higiacomo , I think the "_each field has a toggle_" approach would make it more difficult for users to write custom field types. And since not everybody will be using multi-language, this would be bad UX for the developer - for each custom field they'd have to create a functionality that they don't actually use. But you do bring up a good point - how would we include/highlight the fields that are non-translatable? Do you have any ideas?
@zschuessler , you bring up a good point too. I'll take a look if we can release this as a separate package, that might be cleaner. But even if we don't, everything will live inside one trait and the "edit/create" view will only have one line inserted - that dropdown. So it shouldn't complicate the developer's UX or add any bloat to the package. But you're right - we will need to make some choices and this will make Backpack more opinionated. But the lack of multilanguage makes Backpack useless for some projects, so I think an opinionated option is better than no option. Plus, the interface is just based on views. In a not-too-distant Backpack\Base version I plan on launching "themes". If you like another way to do it, you can just use a different theme (it will just be a bunch of blade, css and js files). Or create your own theme, just for your projects or your company. Or open-source it so anybody else can use it. So that should solve it, right? :-)
Thanks for the feedback guys. Please keep it coming. I'll be working on this as soon as this week, so the sooner your opinions are expressed, the better.
Cheers!
Just wanted to chime in with an example on how to show which fields are translatable / non translatable. In Craft CMS it is done with a little tag style label next to the field label that shows the current language code of the field content. If the field is not translatable no language code is shown. Look at the video on this page for an example. Maybe something similar could be done for Laravel Backpack?
You can probably get away with something like

However i'd highly recommend setting a config item like 'show_translatable_field_icon' => true/false
This would allow the icon to be hidden, you could additionally have 'translatable_field_icon' => 'fa-language' allowing users to toggle it.
Personally I'd have the icon disabled, I don't feel the user needs an extra icon next to them, I think its just UI bloat people are adding based on a concept of "the user needs to know what fields are translatable" where I feel in reality, this probably isn't the case, I don't really see many users getting confused in a real life situation, I think the interface would be obvious enough as it is and it may be over-engineering it + extra markup/code for people who dont want it (unless you're injecting it via js)
TL;DR Keep it simple, don't assume the user will need things because you've done/seen it in the past.
@reekris , thanks, Craft is really nailing some things, it's very good to know how they do things.
@OwenMelbz , I agree, we should give developers the option of not having these. And yes, it's a bummer to insert code in all fields for this. I'll try to avoid that.
Personally, I think it makes more sense to highlight to the user which fields are NOT translatable. The current language is highlighted in the box-header, and the user has probably already clicked to edit that particular language. So it's no new information for him that most fields will be to edit that translation. What I think we _should_ make obvious at this point is the fields that are cross-translation:
What do you guys think about something like this?

I think that would make more sense, less is more :)
However I would think we'd need to consider the positioning of the icons as if people are using prefix/suffix on their fields and if people are marking fields as required like my screenshot then it could get a bit busy (that's why I aligned mine out of the way)
Unless you've got any better ideas?
Deal! It sounds like we've got a front-end :-) Anybody else that want to weight in with alternatives, please do.
On the back-end I'll first try to make an interface for both packages, so that it would work with both dimsav/laravel-translatable and spatie/laravel-translatable, depending on what trait your model is using. Should be perfectly possible, will come back to you guys if it's not.
Cheers! Over and out! :-)
I really like your CMS and cannot wait for the translatable fields!
A short question though: Will it be possible to translate slugs? And if so, will there also be an option to call those slugs directly (in the language the user is currently viewing the website)? (like https://github.com/doitonlinemedia/TranslatableRoutes)
I'm happy to tell you we've _finally_ got a fully-working solution on the multilanguage branch :-)


If anyone wants to give it a test-drive, here's how to do that. Please make sure you test drive in a separate branch. Some things might change before final release.
HasTranslations trait on your model, use Backpack's HasTranslations and define what fields are translatable on your model. For example:namespace App\Models;
use Backpack\CRUD\CrudTrait;
use Illuminate\Database\Eloquent\Model;
use Backpack\CRUD\ModelTraits\SpatieTranslatable\HasTranslations;
class Product extends Model
{
use CrudTrait;
use HasTranslations;
/*
|--------------------------------------------------------------------------
| GLOBAL VARIABLES
|--------------------------------------------------------------------------
*/
protected $table = 'products';
protected $primaryKey = 'id';
protected $fillable = ['name', 'category_id', 'options', 'price', 'tags'];
protected $translatable = ['name', 'options'];
I've tried it with all reasonable fields, columns, features and use cases - it _looks to me_ like it works as intended. But it's a big important feature, so please tell me if you find anything I didn't.
Thanks, cheers!
A. Currently it only supports the way spatie/laravel-translatable does translations, but it's done in such a manner that adding dimsav/laravel-translatable will be a non-breaking change. I call them adapters. Switching between one way and the other should be as easy as changing a trait in your model.
B. You'll probably get errors if you already had entries in that table, because the translatable columns don't have JSONs in them. So it's best to start with a fresh table.
C. When you go to edit a French translation, you'll notice ?locale=fr in the address bar. There's also a hidden input inside the edit form, with the name "locale", that uses that value. Do you think it's too common and it might conflict with anyone's app? Why would you call an attribute or db column "locale" if it's not the locale?
Fantastic :D
However... Personally I'm not keen on that little racing flag haha! Personally I'd use the language icon from FontAwesome http://fontawesome.io/icon/language/
I've also noticed many other CMSs/frameworks use that icon, but its your software :D
This feature have some PHP7 only sintaxis. I like it but i think it should be noted somewhere.
One question. Can Fake Fields be translated?
@imagina can you give an example of the php7 specific syntax?
For example the Null coalescing operator: ??
$locale = $attributes['locale'] ?? \App::getLocale();
Ah right cool, did you say this is used within backpack then? Or the translatable package by spatie? (As we can't do much about that) ?
It seems Pagemanager and some other Backpack packages don't work with the "multilanguage" branch, are there any safe "tweaks"?
Heads up:
I've renamed Backpack\CRUD\ModelTraits\Translatable\SpatieTranslatableAdaptor to Backpack\CRUD\ModelTraits\SpatieTranslatable\HasTranslations, so anyone using SpatieTranslatableAdaptor in their models, please change it. Complete example below. I've made this change in order to preserve consistency: all classes that are overwritten by Backpack now have the same name as the class it overwrites. This will make them easier to use, easier to understand and easier to search.
The latest push will make cviebrock/eloquent-sluggable work with spatie/laravel-translatable. It's pretty "plug-and-play", you just need to use the included traits instead of the ones provided by eloquent-sluggable. Please note: you need MySQL 5.7 to use cviebrock/eloquent-sluggable and spatie/laraveltranslatable (or PosgreSQL with JSON column compatibility). Otherwise features like findBySlug() and findBySlugOrFail() won't work. I found no way around it, the queries were way too slow without this mysql version. And it was a hack anyway. It's a pain to upgrade, I know, I've gone through it myself, but in the end it's worth it. Laravel keeps pushing us to adopt the latest version (PHP 7+, MySQL 5.7+), so let's just do it. @AurelDragut , this will make it easier to integrate with PageManager when Laravel 5.4 rolls around (in a few days).
--
Here's a complete translatable model definition, with the renamed SpatieTranslatableAdaptor, and that uses eloquent-sluggable:
<?php
namespace Backpack\NewsCRUD\app\Models;
use Illuminate\Database\Eloquent\Model;
use Backpack\CRUD\CrudTrait;
use Backpack\CRUD\ModelTraits\SpatieTranslatable\Sluggable;
use Backpack\CRUD\ModelTraits\SpatieTranslatable\SluggableScopeHelpers;
use Backpack\CRUD\ModelTraits\SpatieTranslatable\HasTranslations;
class Category extends Model
{
use CrudTrait;
use Sluggable, SluggableScopeHelpers;
use HasTranslations;
/*
|--------------------------------------------------------------------------
| GLOBAL VARIABLES
|--------------------------------------------------------------------------
*/
protected $table = 'categories';
protected $primaryKey = 'id';
// public $timestamps = false;
// protected $guarded = ['id'];
protected $fillable = ['name', 'parent_id'];
// protected $hidden = [];
// protected $dates = [];
protected $translatable = ['name', 'slug'];
/**
* Return the sluggable configuration array for this model.
*
* @return array
*/
public function sluggable()
{
return [
'slug' => [
'source' => 'slug_or_name',
],
];
}
}
Any feedback on the new translatable & eloquent-sluggable feature is welcome, of course. Especially as it will be included in the next CRUD version in a few days, when Laravel 5.4 launches.
Cheers!
PS. Also updated the new syntax in the comment above.
What's the status ?
hello @tabacitu
i would like to test this branch, could you please update multilang branch to fetch last 3.2 commits?
thanks in advance,
pxpm
@pxpm 3.2 is already using the multilanguage branch. So if you download 3.2 you will have translateable fields
sorry for not paying attention to that. and thanks for answering @petyots .
Sorry for bothering you with this, could you please enlight me how can i refactor this code to work with L5.4
$config_items = app('config')->all();
$this->app['config'] = $this->app->share(function($app) use ($config_items)
{
return $app->make('App\ConfigWritter\Repository', $config_items);
});
share is not supported by laravel anymore... thanks
I am not quite sure but you can try this, it's not tested btw
$config_items = app('config')->all();
$this->app['config'] = $this->app->singleton(function($app) use ($config_items)
{
return $app->make('App\ConfigWritter\Repository', $config_items);
});
Or
$config_items = app('config')->all();
$this->app['config']=$this->app->singleton('App\ConfigWritter\Repository', function ($app) use($config_items) {
return new App\ConfigWritter\Repository($config_items);
});
Hi @tabacitu
I am using the latest version 3.2 of backpack CRUD, with mysql 5.7 and multinglang models, it works perfectly with the example above and when I set the column type to text, but if I use json for the column type then I get the following error when calling $this->crud->setFromDb(); from the controller. Have you experienced this error before or is it just not possible to use the setFromDb() when using JSON columns?
DBALException in AbstractPlatform.php line 423:
Unknown database type json requested, Doctrine\DBAL\Platforms\MySQL57Platform may not support it.
in AbstractPlatform.php line 423
at AbstractPlatform->getDoctrineTypeMapping('json') in MySqlSchemaManager.php line 126
at MySqlSchemaManager->_getPortableTableColumnDefinition(array('field' => 'name', 'type' => 'json', 'null' => 'NO', 'key' => '', 'default' => null, 'extra' => '', 'comment' => '', 'characterset' => null, 'collation' => null, 'name' => '')) in AbstractSchemaManager.php line 820
at AbstractSchemaManager->_getPortableTableColumnList('brands', 'site-manager-backpack', array(array('Field' => 'id', 'Type' => 'int(10) unsigned', 'Null' => 'NO', 'Key' => 'PRI', 'Default' => null, 'Extra' => 'auto_increment', 'Comment' => '', 'CharacterSet' => null, 'Collation' => null), array('Field' => 'name', 'Type' => 'json', 'Null' => 'NO', 'Key' => '', 'Default' => null, 'Extra' => '', 'Comment' => '', 'CharacterSet' => null, 'Collation' => null), array('Field' => 'brand_code', 'Type' => 'varchar(191)', 'Null' => 'NO', 'Key' => 'UNI', 'Default' => null, 'Extra' => '', 'Comment' => '', 'CharacterSet' => 'utf8mb4', 'Collation' => 'utf8mb4_unicode_ci'), array('Field' => 'login_domain', 'Type' => 'json', 'Null' => 'NO', 'Key' => '', 'Default' => null, 'Extra' => '', 'Comment' => '', 'CharacterSet' => null, 'Collation' => null), array('Field' => 'shell_domain', 'Type' => 'json', 'Null' => 'NO', 'Key' => '', 'Default' => null, 'Extra' => '', 'Comment' => '', 'CharacterSet' => null, 'Collation' => null), array('Field' => 'mail_from_address', 'Type' => 'json', 'Null' => 'NO', 'Key' => '', 'Default' => null, 'Extra' => '', 'Comment' => '', 'CharacterSet' => null, 'Collation' => null), array('Field' => 'created_at', 'Type' => 'timestamp', 'Null' => 'YES', 'Key' => '', 'Default' => null, 'Extra' => '', 'Comment' => '', 'CharacterSet' => null, 'Collation' => null), array('Field' => 'updated_at', 'Type' => 'timestamp', 'Null' => 'YES', 'Key' => '', 'Default' => null, 'Extra' => '', 'Comment' => '', 'CharacterSet' => null, 'Collation' => null))) in AbstractSchemaManager.php line 175
at AbstractSchemaManager->listTableColumns('brands') in AbstractSchemaManager.php line 281
at AbstractSchemaManager->listTableDetails('brands') in Connection.php line 843
at Connection->getDoctrineColumn('brands', 'id') in Builder.php line 121
at Builder->getColumnType('brands', 'id') in AutoSet.php line 53
at CrudPanel->getDbColumnTypes() in AutoSet.php line 17
at CrudPanel->setFromDb() in BrandCrudController.php line 33
at BrandCrudController->setUp() in CrudController.php line 39
at CrudController->Backpack\CRUD\app\Http\Controllers\{closure}(object(Request), object(Closure)) in Pipeline.php line 131
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in Admin.php line 29
at Admin->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in SubstituteBindings.php line 41
at SubstituteBindings->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in VerifyCsrfToken.php line 65
at VerifyCsrfToken->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in ShareErrorsFromSession.php line 49
at ShareErrorsFromSession->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in StartSession.php line 64
at StartSession->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in AddQueuedCookiesToResponse.php line 37
at AddQueuedCookiesToResponse->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in EncryptCookies.php line 59
at EncryptCookies->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in Pipeline.php line 102
at Pipeline->then(object(Closure)) in Router.php line 561
at Router->runRouteWithinStack(object(Route), object(Request)) in Router.php line 520
at Router->dispatchToRoute(object(Request)) in Router.php line 498
at Router->dispatch(object(Request)) in Kernel.php line 174
at Kernel->Illuminate\Foundation\Http\{closure}(object(Request)) in Pipeline.php line 30
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in TransformsRequest.php line 30
at TransformsRequest->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in TransformsRequest.php line 30
at TransformsRequest->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in ValidatePostSize.php line 27
at ValidatePostSize->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in CheckForMaintenanceMode.php line 46
at CheckForMaintenanceMode->handle(object(Request), object(Closure)) in Pipeline.php line 148
at Pipeline->Illuminate\Pipeline\{closure}(object(Request)) in Pipeline.php line 53
at Pipeline->Illuminate\Routing\{closure}(object(Request)) in Pipeline.php line 102
at Pipeline->then(object(Closure)) in Kernel.php line 149
at Kernel->sendRequestThroughRouter(object(Request)) in Kernel.php line 116
at Kernel->handle(object(Request)) in index.php line 53
at require('/Users/alfhenderson/workspace/site-manager/public/index.php') in server.php line 133
@alfhen the error clearly explains the problem :)
It tells you it's from Doctrine.
Your best off asking over at Doctrine for how to support the json field type :)
@OwenMelbz, yeah indeed, I was just hoping you might have experienced this already, but I found a solution: By adding this to the boot method of the AppServiceProvider.
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('json', 'text');
@alfhen hi there. i experienced the same problem you did.
If you look at Doctrine on Github you will find a solution.
Basically is creating a new adapted for supporting json.
There is a PR already submited but not merged yet.
Also you will have problems if working with xampp in the lastest versions because MariaDB (the default that come with it) does not provide fully support to json columns natively.
If you map that to text probably the spatie functions for translating json fields are not going to work as it uses native json functions.
@pxpm Thanks for that it is helpfull, info! 馃憤 馃槃
Hi everyone! I've managed to get this working smoothly, can you please tell me if there is an easy way to access the translations in the views? I've created a TranslationsHelper Trait, that fills an array with the translatable fields.
Here is my code:
namespace App\Models\Traits;
trait TranslationsHelper
{
/**
* Fills the translation attribute of the current model
* based on the translatable attribute
*/
public function fillTranslations() {
$trans = array();
foreach ($this['translatable'] as $value)
$trans[$value] = $this->$value;
$this['translations'] = $trans;
}
}
By using this trait in my model, and calling $myModel->fillTranslations(); _(in the controller)_ I can access the translations like this: $myModel['translations']['title'].
Is this correct? Thanks!
What about dimsav/translatable support?
Hello,
i'm learning laravel. I'm using laravel translation table. But i can't join admin panel and frontend. How i learn and let me know tutorial.
Thanks
Hi @zinnia-visible
Welcome to our community. We use github only for issues/features and small info.
If you want some additional support from the community you should ask on stackoverflow or join our gitter chatroom in https://gitter.im/BackpackForLaravel/Lobby
Also our Documentation should help you in getting started.
Best,
Most helpful comment
BOOM!
I'm happy to tell you we've _finally_ got a fully-working solution on the
multilanguagebranch :-)Screenshots
Test drive
If anyone wants to give it a test-drive, here's how to do that. Please make sure you test drive in a separate branch. Some things might change before final release.
HasTranslationstrait on your model, use Backpack'sHasTranslationsand define what fields are translatable on your model. For example:I've tried it with all reasonable fields, columns, features and use cases - it _looks to me_ like it works as intended. But it's a big important feature, so please tell me if you find anything I didn't.
Thanks, cheers!
Notes & Questions
A. Currently it only supports the way spatie/laravel-translatable does translations, but it's done in such a manner that adding dimsav/laravel-translatable will be a non-breaking change. I call them adapters. Switching between one way and the other should be as easy as changing a trait in your model.
B. You'll probably get errors if you already had entries in that table, because the translatable columns don't have JSONs in them. So it's best to start with a fresh table.
C. When you go to edit a French translation, you'll notice ?locale=fr in the address bar. There's also a hidden input inside the edit form, with the name "locale", that uses that value. Do you think it's too common and it might conflict with anyone's app? Why would you call an attribute or db column "locale" if it's not the locale?