Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@
Django Lingua Changelog
========================

Version 0.1, 22nd February 2010
Version 0.9.0, 11th February 2016
========================
Initial Release
Version 0.9.0

Version 0.8.1, 13th November 2010
========================
Version 0.8.1

Version 0.8.0, 12th November 2010
========================
Version 0.8.0

Version 0.8.1, 13th November 2010
Version 0.1, 22nd February 2010
========================
Version 0.8.1
Initial Release

9 changes: 9 additions & 0 deletions HISTORY.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
Version 0.9.0
-------------
- adapt code for supporting Django >= 1.9
- Use py file instead of an html file with trans.
- Place created translations python file in each related app. Better maintainability.
- Inherits from an abstract Translation Model
- Rework admin
- Add LINGUA_DEFAULT settings (set the msgid key language, default to 'en').

Version 0.8.0
--------------
- access direct the field translation i.e. <field>_<lang> name_de or name_es
Expand Down
14 changes: 9 additions & 5 deletions HOWTO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
from django.db import models
from lingua import translation

class Table(models.Model):
class Translation(translation.Translation):
name = models.CharField(max_length=32)
class Table(translation.TranslationModel):
name = models.CharField(max_length=32)
_translation_fields = ('name',)

5. Active the admin(optional)
from lingua.admin import LinguaModelAdmin
Expand All @@ -30,11 +30,15 @@

admin.site.register( SomeModel, SomeAdminClass )

You can set `LINGUA_DEFAULT` to a specified language in you settings (default to 'en').
In the admin, it will display only your msgid and languages msgstr except for 'en' language
which is in most case the msgid language.

6. Fill some data into the database to translate

7. Run ./manage.py collectmessages

It will fetch all data to translate and store them into the file 'db_translation.html'.
It will fetch all data to translate and store them into the file 'extra_translations.py' for each app.

8. Run django-admin.py makemessages -l <lang>

Expand All @@ -44,7 +48,7 @@
10. Run django-admin.py compilemessages

11. In the view you can use like <field_name>_<lang>, i.e. name_de or name_es.
Use <field_name>_00 to get the original value
Use <field_name>_00 to get the original value.

Done!

Expand Down
3 changes: 3 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
Copyright (c) Guillaume Cisco


Copyright (c) aquarianhouse.com | Georg Kasmin.
All rights reserved.

Expand Down
8 changes: 7 additions & 1 deletion README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@ Reduce the database hits to 0
* Translate it directly in the admin interface
* Access the translation to each field to each language

Works >= 1.0
Compatible Django >= 1.9
Should work for previous version of Django, not tested yet.


TODO:
Find a way to mixin the model without using a mixin model.
Maybe use `contribute_class` as used before.
3 changes: 2 additions & 1 deletion lingua/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
VERSION = (0, 8, 1)
VERSION = (0, 9, 0)
__version__ = ".".join(map(str, VERSION))


def get_version():
return __version__
58 changes: 13 additions & 45 deletions lingua/admin.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,8 @@
"""
File: admin.py

Copyright (c) aquarianhouse.com | Georg Kasmin.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

3. Neither the name of Django nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
from django.contrib import admin
from django import forms
import os, sys
import os
import polib
from django.apps import apps


class LinguaModelAdmin(admin.ModelAdmin):

Expand All @@ -47,11 +17,12 @@ def get_fields_with_type(model, fields_type):
return fields

@staticmethod
def get_fields(model):
return ['_'.join((field, l)) for field in model._translation_fields for l in model._languages.keys()]
def get_admin_fields(request, obj=None):
return ['_'.join((field, l)) for field in obj._translation_fields for l in obj._languages.keys()]


def get_form(self, request, obj=None, **kwargs):
kwargs['fields'] = None
form = super(LinguaModelAdmin, self).get_form(request, obj, **kwargs)

class LinguaAdminForm(form):
Expand Down Expand Up @@ -80,14 +51,11 @@ def save(self, *args, **kwargs):
from django.conf import settings
from lingua.utils import clear_gettext_cache

#TODO make pretty
if settings.SETTINGS_MODULE is not None:
parts = settings.SETTINGS_MODULE.split('.')
project = __import__(parts[0])
self.projectpath = os.path.join(os.path.dirname(project.__file__), 'locale')
if model._meta.app_label:
self.projectpath = os.path.join(apps.app_configs[model._meta.app_label].path, 'locale')
self.languages_po = {}
for l in dict(settings.LANGUAGES).keys():
p = os.path.join(self.projectpath, l, 'LC_MESSAGES', 'django.po')
p = os.path.join(self.projectpath, l, 'LC_MESSAGES', 'django.po')
if os.path.exists(p):
self.languages_po[l] = polib.pofile(p)

Expand All @@ -105,7 +73,7 @@ def save(self, *args, **kwargs):
entry = polib.POEntry(msgid=msgid, msgstr=c)
po.append(entry)

for k,p in self.languages_po.items():
for k, p in self.languages_po.items():
p.save()
path = os.path.join(self.projectpath, k, 'LC_MESSAGES', 'django.mo')
p.save_as_mofile(path)
Expand All @@ -118,10 +86,10 @@ def save(self, *args, **kwargs):
return LinguaAdminForm

def get_fieldsets(self, request, obj=None):
fields = super(LinguaModelAdmin,self).get_fieldsets(request,obj)
form = self.get_form(request, obj)
fields = super(LinguaModelAdmin,self).get_fieldsets(request, obj)
form = self.get_form(request, obj, fields=None)
model = form._meta.model
fields[0][1]["fields"] += LinguaModelAdmin.get_fields(model)
fields[0][1]["fields"] += LinguaModelAdmin.get_admin_fields(request, model)
return fields


34 changes: 1 addition & 33 deletions lingua/handler.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,6 @@
"""
File: handlers.py

Copyright (c) aquarianhouse.com | Georg Kasmin.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

3. Neither the name of Django nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

from django.utils.translation import ugettext_lazy as _


def post_init(sender, instance, **kwargs):
"""Class is ready, all attributes has been set """
"""Loop through translation fields and set the gettext in beetween """
Expand All @@ -40,4 +9,3 @@ def post_init(sender, instance, **kwargs):
value = getattr(instance, x)
setattr(instance, x, _(value))
setattr(instance, "_".join((x,"00")), value)#original value

11 changes: 0 additions & 11 deletions lingua/manage.py

This file was deleted.

86 changes: 41 additions & 45 deletions lingua/management/commands/collectmessages.py
Original file line number Diff line number Diff line change
@@ -1,59 +1,55 @@
"""
File: collectmessages.py

Copyright (c) aquarianhouse.com | Georg Kasmin.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

3. Neither the name of Django nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
from django.core.management import BaseCommand, CommandError
from django.db import models
from django.utils.encoding import smart_str
from django.apps import apps
from django.db import models, router, connections, DEFAULT_DB_ALIAS
from collections import OrderedDict
from django.utils.translation.trans_real import all_locale_paths, check_for_language, language_code_re, to_locale
import gettext as gettext_module
import os
from django.core.files import File


class Command(BaseCommand):
help = "Translate database messages"

requires_model_validation = False

def add_arguments(self, parser):
parser.add_argument('--database', action='store', dest='database',
default=DEFAULT_DB_ALIAS, help='Nominates a database to synchronize. '
'Defaults to the "default" database.')

def handle(self, *args, **options):
db_values = []
""" Taken from django.core.management.commands.syncdb"""
for app in models.get_apps():
model_list = models.get_models(app, include_auto_created=True)

"""Performance is not so important, we do it once... """
db = options.get('database')
connection = connections[db]
connection.prepare_database()

# Build the manifest of apps and models that are to be synchronized
all_models = [
(app_config.label,
router.get_migratable_models(app_config, connection.alias, include_auto_created=False))
for app_config in apps.get_app_configs()
]

for app_name, model_list in all_models:
for m in model_list:
if hasattr(m, '_translation_fields'):
for x in m._translation_fields:
for y in m.objects.all():
db_values.append( getattr(y, x) )

#print db_values
f = file('db_translation.html', "w")
""" blocktrans and we dont have to worry about to escape the string etc."""
for v in db_values:
f.write('{%% blocktrans %%}%s{%% endblocktrans %%}\n' % smart_str(v))
f.close()
db_values.append(getattr(y, x))

path = apps.app_configs[app_name].path
# print db_values
with open(os.path.join(path, 'extra_translations.py'), 'w') as f:
translations_file = File(f)
translations_file.write('''# encoding: utf-8

from __future__ import unicode_literals, absolute_import
from django.utils.translation import ugettext_lazy as _

translations = (
''')
for v in db_values:
translations_file.write(""" _('%s'),\n""" % smart_str(v.replace('\'', '\\\'')))
translations_file.write(')')
Loading