Anahkiasen / polyglot

Laravel localization and translation helper
130 stars 22 forks source link

Other languages #16

Closed taai closed 10 years ago

taai commented 10 years ago

Now I want to add Latvian translation. It can be done by adding

public function lv()
{
    return $this->hasOne($this->getLangClass())->whereLang('lv');
}

to my model or by creating my custom Polyglot base model that I extend my other models from.

But I find it cumbersome, because there are 10 translation methods (languages) in the Polyglot class already, except Latvian (and so many more). Either add all languages (and make Polygot class huge with ~100 language methods) or better - create mechanism that makes it possible to define languages that are supported in my model!

I suggest to add this to the __get() method:

// If relation is already loaded, return it
if (array_key_exists($key, $this->relations))
{
    return $this->relations[$key];
}

if (in_array($key, $this->locales))
{
    $relation = $this->hasOne($this->getLangClass())->whereLang($key);
    return $this->relations[$key] = $relation->getResults();
}

then I just have to set supported languages in my model:

protected $locales = array('lv', 'en', 'fr');

With this solution there is no need for language methods anymore.

Please, consider this and tell me why this solution wouldn't be better! :)

Anahkiasen commented 10 years ago

This is what I used to do but that didn't work because there was a method_exists at some point in Eloquent's relation mechanisms that prevented me from making it work. But it was a while back, maybe it changed. I'll see to regive it a shot.

taai commented 10 years ago

@Anahkiasen Yes, there still is the method_exists and it's ok. If you would look at the Eloquent\Model class, you will see that __get() calls $this->getAttribute($key) which then checks if there is an attribute or a relation and then - if there is a method -, which then gets called and the relation is being loaded into $this->relations. As you can see, my code does the same thing what Eloquent\Model class does. There is no need to do the round-trip to load the relation out of the language method. They all goes true the __get() anyway.

Anahkiasen commented 10 years ago

No I know that. It's not the fetching that didn't work, it was the eager loading. Which can get quite problematic when your model's data is on two tables. Not sure if it'd work now but then doing model::with('fr') if fr wasn't explicitely defined wouldn't load anything.

taai commented 10 years ago

@Anahkiasen Easy! Add this:

public function __call($langOrMethod, $parameters)
{
    // If model supports the locale, load it as a relation
    if (in_array($langOrMethod, $this->locales))
    {
        return $this->hasOne($this->getLangClass())->whereLang($langOrMethod);
    }

    return parent::__call($langOrMethod, $parameters);
}
Anahkiasen commented 10 years ago

Well I don't have much time lately to work on Polyglot but if you're sure that works you can send a PR to the develop branch and I'll be happy to accept it.

MathieuDoyon commented 10 years ago

@taai could you try this fix 24a645d