GithubHelp home page GithubHelp logo

2amigos / yii2-translateable-behavior Goto Github PK

View Code? Open in Web Editor NEW
66.0 23.0 28.0 65 KB

Handles ActiveRecord's attribute translations

License: BSD 3-Clause "New" or "Revised" License

PHP 100.00%

yii2-translateable-behavior's Introduction

TranslateableBehavior for Yii2

This behavior has been inspired by the great work of Mikehaertl's Translatable Behavior for Yii 1.*.

It eases the translation of ActiveRecord's attributes as it maps theme from a translation table into the main record. It also automatically loads application language by default.

Sample of use:

<?php

// create a record
$tour = new Tour;

$tour->title = "English title";

// save both the new Tour and a related translation record with the title
$tour->save();


// change language
$tour->language = 'fr';

$tour->title = "French title";

// save translation only
$tour->saveTranslation();

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require "2amigos/yii2-translateable-behavior"

or add

"2amigos/yii2-translateable-behavior" : "~1.1"

to the require section of your application's composer.json file.

Usage

Preparation

First you need to move all the attributes that require to be translated into a separated table. For example, imagine we wish to keep translations of title and description from our tour entity. Our schema should result on the following:

    +--------------+        +--------------+        +-------------------+
    |     tour     |        |     tour     |        |      tour_lang    |
    +--------------+        +--------------+        +-------------------+
    |           id |        |           id |        |                id |
    |        title |  --->  |   created_at |   +    |           tour_id |
    |  description |        |   updated_at |        |          language |
    |   created_at |        +--------------+        |             title |
    |   updated_at |                                |       description |
    +--------------+                                +-------------------+

After we have modified our schema, now we need to define a relation in our ActiveRecord object. The following example assumes that we have already created a TourLang model (see the schema above):

/**
* @return \yii\db\ActiveQuery
*/
public function getTranslations()
{
    return $this->hasMany(TourLang::className(), ['tour_id' => 'id']);
}

Finally, we need to attach our behavior.

use dosamigos\translateable\TranslateableBehavior;

\\ ...

public function behaviors()
{
    return [
        'trans' => [ // name it the way you want
            'class' => TranslateableBehavior::className(),
            // in case you named your relation differently, you can setup its relation name attribute
            // 'relation' => 'translations',
            // in case you named the language column differently on your translation schema
            // 'languageField' => 'language',
            'translationAttributes' => [
                'title', 'description'
            ]
        ],
    ];
}

Basic Usage

// create a record
$tour = new Tour;
$tour->title = "English title";

// save both the new Tour and a related translation record with the title
$tour->save();


// change language
$tour->language = 'fr';

$tour->title = "French title";

// save fr translation only
$tour->saveTranslation();

You may also set multiple translations directly:

$tour = new Tour;
$tour->title = [
  'translations' => [
     'en' => "English title",
     'de' => "Deutscher Titel",
  ],
];

// save both the new Tour and a related translation record with the title
$tour->save();

Fallback language

In case no translation is available for a specific language the behavior allows to specify a fallback translation to load instead. By default the fallback will use the application source language. It can be configured by setting the fallbackLanguage property of the behavior.

Fallback language can be configured to be a single language or per language:

// use english as fallback for all languages when no translation is available
'fallbackLanguage' => 'en',
// alternatively:
'fallbackLanguage' => [
    'de' => 'en', // fall back to English if German translation is missing
    'uk' => 'ru', // fall back to Russian if no Ukrainian translation is available
],

Additionally to the configurable fallback a fallback to non-localized language is applied automatically. E.g. if no translation exists for de-AT (German in Austria) the translation will fall back to de. The fallback goes further if de is not found using the fallbackLanguage configuration, so from the example above it will then try en.

When the fallback is defined in array format and no fallback can be found for a language, the first fallback is returned.

You may disable the fallback mechanism by setting fallbackLanguage to false.

If you want to configure fallback languages globally, you can do so by configuring the TranslateableBehavior class in Yii DI container:

Yii::$container->set('dosamigos\translateable\TranslateableBehavior', ['fallbackLanguage' => 'de']);

Deleting translations

By default, when an active record is deleted, translation records are deleted in the afterSave event. However some database scenarios require different configuration, in case foreign keys restrict the deletion of records.

You may configure 'deleteEvent' to be either ActiveRecord::EVENT_BEFORE_DELETE or ActiveRecord::EVENT_AFTER_DELETE to control on which event the deletion of records should be performed. You may set 'deleteEvent' to false to disable deletion and rely on DB foreign key cascade or implement your own method.

When using the Translateablebehavior in an ActiveRecord you should enable transactions() for the delete operation.

2amigOS!
Web development has never been so fun!
www.2amigos.us

yii2-translateable-behavior's People

Contributors

amigo-tabin avatar cebe avatar gatis-ozols avatar handcode avatar hector-del-rio avatar kurpievski avatar mrstroz avatar schmunk42 avatar sohelahmed7 avatar tonydspaniard avatar vintik100 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

yii2-translateable-behavior's Issues

Default translation

It would be nice if it was possible to define a default translation in case of missing
Eg: My site is in 'pt-pt' but I have only translations in 'en-gb'... i think is preferible see the info in another language, than no info at all...
Thank you!

Validation error at saving translation remains hidden.

I have the following validation in model IngredientGroupLang:

    public function rules()
    {
        return [
            [['ingredient_group_id', 'language', 'name'], 'required'],
            [['ingredient_group_id'], 'integer'],
            [['language', 'name'], 'string', 'max' => 255],
            [['language', 'name'], 'unique', 'targetAttribute' => ['language', 'name']],
        ];
    }

Uniqueness validation error of IngredientGroupLang at saving of an instance of IngredientGroup remains hidden, what causes that theIngredientGroup will be saved without IngredientGroupLang record, causing an inconsistent database. Even if I overwrite the save method of IngredientGroup to run in transaction, it does not help, because I can not catch the validation error of the translation.

I think, the problem is, that validation error at saving the translation should raise an exception and the validation error should be bubbled up into the main model instance. The exception could than be catched.

Do you have any idea? I need a uniqueness validation on the name attribute.

Search on ID in default GridView gives SQL error

I get the following SQL error on search on the ID field:

Integrity constraint violation โ€“ yii\db\IntegrityException
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous
The SQL being executed was: SELECT COUNT(*) FROM `re_ingredient_group` LEFT JOIN `re_ingredient_group_lang` ON `re_ingredient_group`.`id` = `re_ingredient_group_lang`.`ingredient_group_id` WHERE (`id`='1') AND (`re_ingredient_group_lang`.language='en-US')

Error Info: Array
(
    [0] => 23000
    [1] => 1052
    [2] => Column 'id' in where clause is ambiguous
)

Caused by: PDOException
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous

The error is quite clear, the ID field in the where clause is not qualified by the table name. Any idea how to achieve, that the fully qualified field name is used?

my Has_Many function has a "andOnCondition" but its not used

Hi,
I am storing for different accounts separate translations via your model.
But that means that I am using this

 return $this->hasMany(Translation::class, ['fk_id' => 'field_id'])
        ->andOnCondition(['customer_id' => Yii::$app->session['active_customer_id']])
        ;

But somehow the query that your behavour fires, does not include the andOn condition.
Am I doing something wrong?

Thanks for any hint....

gb5256

translationAttributes requires language attribute

Assumption

I have same schema as
https://github.com/2amigos/yii2-translateable-behavior#preparation

this is behavior config in tour model

public function behaviors()
{
    return [
        'trans' => [ // name it the way you want
            'class' => TranslateableBehavior::className(),
            // in case you named your relation differently, you can setup its relation name attribute
            // 'relation' => 'translations',
            // in case you named the language column differently on your translation schema
            // 'languageField' => 'language',
            'translationAttributes' => [
                'title', 'description'
            ]
        ],
    ];
}

Now when i save model in actionCreate as

$tour_model->lang = 'en';

getting error

yii\base\UnknownPropertyException: Setting unknown property:
\models\Tour::lang in ...

now i add a lang in behavior as

'translationAttributes' => [
                'title', 'description', 'lang'
            ]

and having below line in controller, all works fine

$tour_model->lang = 'en';

Is this a issue or doc should be updated?
I think the doc should be updated that lang att should also be in translationAttributes

feel free to ask more details if needed

Translation with tabs

Thanks for this extension, is it possible to extend this and use tabs to display the different languages like this:

ktw4p

Bug when applying limit on query

I'm using the 2amigos/yii2-translateable-behavior, and when I limit the query set (aka, use per-page parameter), the query is returning all translations of records that match the query criteria.

Let me try explain this better, imagine the following scenario:
I have the table ARTICLE, each article can have one or more translations, stored in ARTICLE_LANG table.
I want to return the first 5, if those five only have 1 translation (meaning, original language), I will receive 5 unique records.
Now, imagine this twist, where those 5 records, the 2 first records have 2 translations each, what the query will return is 4 records corresponding to the first two, and the fifth will be ARTICLE no.3

That makes the api return only 3 unique records, instead of the 5 I've requested.
@tonydspaniard

Updating doesn't work

I've installed this great extension and everything works fine with displaying data already in database.
But when i try to update data nothing happens. As far I can see, title property never gets marked as dirty and so never gets updated. I have Article and ArticleTranslation models setup up as by instructions.
This is in my activeForm among other fields.

<?= $form->field($model, 'title')->textInput() ?>

Sorting doesn't work in GridView

Sorting on internationalized fields doesn't work in GridView. The fields in the table header are simple text fields, no links.

Any idea?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.