Looks good so far!
One improvement I can think of would be to use the approach in mezzanine.boot to add the fields to models - that would mean not requiring the (Python) metaclass which would be a simpler API and could prevent metaclass conflicts down the track.
Another idea in the same vein as mezzanine.boot would be to put all the translatable fields into a setting rather than on inner (Django model) Meta classes. This has some pros and cons so I'm not sure if it's a better approach, merely something to think about it.
Pros:
- Users can change the translatable fields without needing to modify Mezzanine or any third party apps.
- One single config point for defining an entire project's translatable fields.
Cons:
- Having the translatable fields declared on Meta classes could be considered more explicit.
With regard to south, I think you've described the same issue that I talked about in field injection caveats, eg: yes the migrations get created, but the migrations get created for apps that the developer shouldn't modify. Here's an example:
- Developer installs Mezzanine
- Developer adds new languages to their settings module
- Developer runs schemamigration on Mezzanine's apps
- Migrations get created inside Mezzanine rather than the project
We can get away with this in some regard with the field injection functionality, as it's an optional extra tool that can be used for customising models. It isn't core functionality and comes with appropriate warnings. I don't think translatable content fits this bill - if it gets added it'll be a core feature. Again I still don't have a solution for this. I feel like there might need to be an approach where migrations get created, then copied to the project somehow.