mikehaertl / translatable

Transparent attribute translation for ActiveRecords
3 stars 5 forks source link

Keep the first-class model attributes and use them when reading/writing content in the source language #5

Open motin opened 11 years ago

motin commented 11 years ago

Example: title & abstract is translated as per the readme. Instead of removing these two fields, keep them, and subsequently get/set/save these first-class attributes as long as the model’s language == the source language.

With source language I am referring to the language in which content is created, which can be either set on a application level (Yii::app()->sourceLanguage) or record ($model->source_language).

Motivation:

  1. The translated fields remain in the place that they are supposed to be, with the correct lengths (for varchar) and other options (null/not null) and thus generated CRUD using gii/gtc will produce ready-to-use CRUD för displaying and saving translations using this behavior, with the correct field orders, validation rules and all.
  2. The behavior works without schema changes to the model table. It is easier to migrate an existing table filled with content to be translated when all one has to do is to create the translations-table and activate the behavior. Prevents data loss and makes the configuration easier.
  3. This is similar to how Yii::t() is used - when the source language is queried for, the gettext-lookup is not performed.
  4. There is often an important distinction between the source language and a translation. When the attribute in the source language changes, the translations needs to be updated. Being überclear about which content is the source language content is A Good Thing.
schmunk42 commented 11 years ago

It depends, but I usually don't remove the fields from the base table, but name them default_title and default_abstract and configure them as fallbacks. This is much more intuitive to use. I used this approach in the upcoming releases of p3widgets, p3media and p3pages. Maybe we can updated the readme with more examples.

As mentioned above you can use configuration to overcome 1.) and 2.), what would be easier concerning configuration with a source_language?

I recently added a disableTranslationModel property which helps you with 3.)

about 4.) just add that field if you want to ;)

motin commented 11 years ago

This is much more intuitive to use. I used this approach in the upcoming releases of p3widgets, p3media and p3pages. Maybe we can updated the readme with more examples. As mentioned above you can use configuration to overcome 1.) and 2.),

Yes, I saw that in the upcoming releases of p3* (nice, btw), and yes it is possible to use configuration to overcome 1) and 2), but I'd like to remove the part of the readme that communicates a need to remove the original fields form the database, ie let the default behavior to be do keep them, and stop calling them fallbacks, they are simply the source messages. source_title & source_abstract maybe? or simply _title & _abstract, or title & abstract (if that still works with the magic getter/setter logic).

After that, it could still be possible to use configuration to be able to remove the attributes from the original model, but that would not be default behavior or even advisable except for special cases.

what would be easier concerning configuration with a source_language?

Record-level distinction of source_language is necessary when users contribute material in different languages.

about 4.) just add that field if you want to ;)

Actually, I wasn't talking about the record-level source_language attribute here, but in general the need to have a source message and a translation. I should have used "source message" instead of "source language content", in order to use the same lingo as in the default yii i18n implementation: SourceMessage vs Message.

I'd say that an attribute without a source message is not a translatable attribute, but simply a multilingual attribute. It does help with specifying different versions of the attribute in different languages, but does not aid in actually translating attributes.

I know it's still unclear, tell me if I should give an example of a real-life case where this matters :)

schmunk42 commented 11 years ago

I see your points, but would also like to hear Mike about this, since it's his project :) He's only sparingly available AFAIK, but hey ... I'd love to hear your real world example in the meantime.

motin commented 11 years ago

Real-life example for 4) is when creating legal or educational content that is be available in many different languages. The content is created and reviewed to be correct in the source language, and then translated (possibly using automatic translation tools, paid translators and/or crowdsourced means). The publisher can only be responsible for the contents in the source language, but provides the other translations for convenience. In this case, being überclear about which content is the source language content is A Good Thing.

motin commented 11 years ago

I recently created an extension based on these principles 1,3 and 4: https://github.com/neam/yii-i18n-attribute-messages 2 is not possible without a schema attribute rename, or else the behavior will not be able to supply logic for the attribute without a language suffix, but at least a console command is included that makes changing the schema very effortlessly.

schmunk42 commented 10 years ago

So, to keep this going, what would you propose to change?

mikehaertl commented 10 years ago

@motin Sorry for the delay. I think i quite like your idea. But as you already started your own project now, I'm not sure if you're still interested in merging both :).

motin commented 10 years ago

Hi Mike! Yes, we will continue to use https://github.com/neam/yii-i18n-attribute-messages but I'd be interested in creating a common interface that both extensions use, so that they basically are interchangeable, for instance by creating a common set of unit tests that both extensions pass.

mikehaertl commented 10 years ago

I'm not sure if it makes much sense to have 2 almost identical extensions, that do the same and would only differ in their implementation. :)

But there's a blocker anyway: You can't override existing AR attributes from a behavior. So while the idea is good, any implementation would be imperfect. In your extension you seem to prefix original columns with a _. Our extension uses a property fallbackColumns to define a similar thing. Both solutions are not 100% perfect, so for now we'll probably stick with fallbackColumns to not break BC.

I'll keep this here open to collect more ideas.

motin commented 10 years ago

I'm not sure if it makes much sense to have 2 almost identical extensions, that do the same and would only differ in their implementation. :)

It makes a lot of sense. Since no implementation is perfect, I use i18n-attribute-messages for some attributes, and i18n-columns for others. They are almost identical in their interface, but very different in their implementation. For other attributes, it could make sense to use translatable instead. Depending on the usage and characteristics of each attribute, one implementation may make more sense than the other.

To give a better idea, here is an example of how I configure the different behaviors: https://gist.github.com/motin/7640171

mikehaertl commented 10 years ago

Well, I'm a big fan of "keep it simple" - which also means to avoid too much diversity. But anyway ...

Here's what I have in mind for Translatable 2.0:

So you'd use it like:

// Source language is always accessible through the unprefixed column name
echo $model->name;
$model->name = 'English name';

// To operate on the translation you'd use the t_ prefix. This will
// read/write from/to the translation table if language!==sourceLanguage,
// and otherwhise operate on the main table
echo $model->t_name;
$model->t_name = 'Translated name';

Pros

Cons

motin commented 10 years ago

Prefixing with t_ as a workaround for the fact that behaviors can't override existing AR attributes takes away the "transparent" effect of simply using $model->name as "before" and have it output in the site's current language, it is not a bad trade-off if one does not want to change the schema. It can be configurable, like "$attributePrefix", where when being left empty would result in todays behavior. A good thing to have in the interface definition :)

"Only join the translation table when really required" can be implemented with or without empty prefix.

mikehaertl commented 10 years ago

You can't leave the prefix empty, as you can't override AR attributes.

I'm also considering a different approach, where you can fetch something like a facade object from each model which contains the translated attributes. But this requires some more thinking first.

motin commented 10 years ago

You can't leave the prefix empty, as you can't override AR attributes.

Very true. Leaving the prefix empty would require the schema change prefixing columns with "_" in the database or similar.

I'm also considering a different approach, where you can fetch something like a facade object from each model which contains the translated attributes. But this requires some more thinking first.

Interesting. Feel free to share any partial thoughts about that approach here :)

schmunk42 commented 10 years ago

ActiveRecordFacade sounds like a great idea.

Would it be a bit like database table views for active records?

Codename proposal: Potemkin ;)

Von meinem iPhone gesendet

Am 27.11.2013 um 09:01 schrieb Fredrik Wollsén notifications@github.com:

You can't leave the prefix empty, as you can't override AR attributes.

Very true. Leaving the prefix empty would require the schema change prefixing columns with "_" in the database or similar.

I'm also considering a different approach, where you can fetch something like a facade object from each model which contains the translated attributes. But this requires some more thinking first.

Interesting. Feel free to share any partial thoughts about that approach here :)

— Reply to this email directly or view it on GitHub.

schmunk42 commented 10 years ago

OK, just to add this: I also stumbled upon the "missing source_language" param recently. For a future release I think it should be a requirement to add a source_language column to your table which has Translatable attached.

mikehaertl commented 10 years ago

Why would we need this in the DB? Isn't it sufficient to set Yii::app()->sourceLanguage? I don't want to put too many constraints on the users of this extension.

schmunk42 commented 10 years ago

But the base record could be still created in any language, there are no rules for that. Or it is just optional and we mention it in the docs.

mikehaertl commented 10 years ago

Can't really see the point. We don't have to overengineer things. The language in the main table usually corresponds to the source language of the application.

schmunk42 commented 10 years ago

Yes, "usually" ;)