i18n for default taiga names

remotes/origin/enhancement/email-actions
Alejandro Alonso 2015-04-14 09:42:34 +02:00
parent 13def945c6
commit 9ef2f709c7
9 changed files with 458 additions and 140 deletions

View File

@ -221,6 +221,7 @@ DEFAULT_FILE_STORAGE = "taiga.base.storage.FileSystemStorage"
LOCALE_PATHS = (
os.path.join(BASE_DIR, "locale"),
os.path.join(BASE_DIR, "taiga", "locale"),
)
SECRET_KEY = "aw3+t2r(8(0kkrhg8)gx6i96v5^kv%6cfep9wxfom0%7dy0m9e"

View File

@ -38,6 +38,7 @@ from django.utils.encoding import smart_text
from django.utils.encoding import force_text
from django.utils.encoding import is_protected_type
from django.utils.functional import Promise
from django.utils.translation import ugettext
from django.utils.translation import ugettext_lazy as _
from django.utils.datastructures import SortedDict
@ -133,6 +134,7 @@ def humanize_strptime(format_string):
class Field(object):
read_only = True
i18n = False
creation_counter = 0
empty = ""
type_name = None
@ -142,7 +144,7 @@ class Field(object):
type_label = "field"
widget = None
def __init__(self, source=None, label=None, help_text=None):
def __init__(self, source=None, label=None, help_text=None, i18n=False):
self.parent = None
self.creation_counter = Field.creation_counter
@ -159,6 +161,7 @@ class Field(object):
self._errors = []
self._value = None
self._name = None
self.i18n = i18n
@property
def errors(self):
@ -271,7 +274,7 @@ class WritableField(Field):
def __init__(self, source=None, label=None, help_text=None,
read_only=False, write_only=False, required=None,
validators=[], error_messages=None, widget=None,
default=None, blank=None):
default=None, blank=None, i18n=False):
# "blank" is to be deprecated in favor of "required"
if blank is not None:
@ -280,7 +283,8 @@ class WritableField(Field):
DeprecationWarning, stacklevel=2)
required = not(blank)
super(WritableField, self).__init__(source=source, label=label, help_text=help_text)
super(WritableField, self).__init__(source=source, label=label,
help_text=help_text, i18n=i18n)
self.read_only = read_only
self.write_only = write_only
@ -486,6 +490,13 @@ class CharField(WritableField):
return value
return smart_text(value)
def to_native(self, value):
ret = super(CharField, self).to_native(value)
if self.i18n:
ret = ugettext(ret)
return ret
class URLField(CharField):
type_name = "URLField"

View File

@ -673,6 +673,7 @@ class ModelSerializerOptions(SerializerOptions):
def __init__(self, meta):
super(ModelSerializerOptions, self).__init__(meta)
self.model = getattr(meta, "model", None)
self.i18n_fields = getattr(meta, "i18n_fields", ())
self.read_only_fields = getattr(meta, "read_only_fields", ())
self.write_only_fields = getattr(meta, "write_only_fields", ())
@ -837,6 +838,11 @@ class ModelSerializer((six.with_metaclass(SerializerMetaclass, BaseSerializer)))
(field_name, self.__class__.__name__))
ret[field_name].write_only = True
# Add the `i18n` flag to any fields that have been specified
# in the `i18n_fields` option
for field_name in self.opts.i18n_fields:
ret[field_name].i18n = True
return ret
def get_pk_field(self, model_field):
@ -929,6 +935,9 @@ class ModelSerializer((six.with_metaclass(SerializerMetaclass, BaseSerializer)))
for attribute in attributes:
kwargs.update({attribute: getattr(model_field, attribute)})
if model_field.name in self.opts.i18n_fields:
kwargs["i18n"] = True
try:
return self.field_mapping[model_field.__class__](**kwargs)
except KeyError:

View File

@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.forms import widgets
from django.utils.translation import ugettext as _
from taiga.base.api import serializers
@ -36,6 +37,37 @@ class JsonField(serializers.WritableField):
return data
class I18NJsonField(JsonField):
"""
Json objects serializer.
"""
widget = widgets.Textarea
def __init__(self, i18n_fields=(), *args, **kwargs):
super(I18NJsonField, self).__init__(*args, **kwargs)
self.i18n_fields = i18n_fields
def translate_values(self, d):
i18n_d = {}
for key, value in d.items():
if isinstance(value, dict):
i18n_d[key] = self.translate_values(value)
if key in self.i18n_fields:
if isinstance(value, list):
i18n_d[key] = [_(e) for e in value]
if isinstance(value, str):
i18n_d[key] = _(value)
else:
i18n_d[key] = value
return i18n_d
def to_native(self, obj):
i18n_obj = self.translate_values(obj)
return i18n_obj
class PgArrayField(serializers.WritableField):
"""
PgArray objects serializer.

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: taiga-back\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-04-14 16:26+0200\n"
"POT-Creation-Date: 2015-04-14 18:00+0200\n"
"PO-Revision-Date: 2015-03-25 20:09+0100\n"
"Last-Translator: Taiga Dev Team <support@taiga.io>\n"
"Language-Team: Taiga Dev Team <support@taiga.io>\n"
@ -1618,160 +1618,236 @@ msgid ""
"[Taiga] Added to the project '%(project)s'\n"
msgstr ""
#: taiga/projects/translations.py:3
msgid "?"
msgstr ""
#: taiga/projects/translations.py:4
msgid "0"
msgstr ""
#: taiga/projects/translations.py:5
msgid "1/2"
msgstr ""
#: taiga/projects/translations.py:6
msgid "1"
msgstr ""
#: taiga/projects/translations.py:7
msgid "2"
msgstr ""
#: taiga/projects/translations.py:8
msgid "3"
msgstr ""
#: taiga/projects/translations.py:9
msgid "5"
msgstr ""
#: taiga/projects/translations.py:10
msgid "8"
msgstr ""
#: taiga/projects/translations.py:11
msgid "10"
msgstr ""
#: taiga/projects/translations.py:12
msgid "15"
msgstr ""
#: taiga/projects/translations.py:13
msgid "20"
msgstr ""
#: taiga/projects/translations.py:14
msgid "40"
msgstr ""
#: taiga/projects/translations.py:15
#. Translators: Name of scrum project template.
#: taiga/projects/translations.py:28
msgid "Scrum"
msgstr ""
#: taiga/projects/translations.py:16
msgid "Archived"
msgstr ""
#: taiga/projects/translations.py:17
msgid "Back"
msgstr ""
#: taiga/projects/translations.py:18
msgid "Bug"
msgstr ""
#: taiga/projects/translations.py:19
msgid "Closed"
msgstr ""
#: taiga/projects/translations.py:20
msgid "Critical"
msgstr ""
#: taiga/projects/translations.py:21
msgid "Design"
msgstr ""
#: taiga/projects/translations.py:22
msgid "Done"
msgstr ""
#: taiga/projects/translations.py:23
msgid "Enhancement"
msgstr ""
#: taiga/projects/translations.py:24
msgid "Front"
msgstr ""
#: taiga/projects/translations.py:25
msgid "High"
msgstr ""
#: taiga/projects/translations.py:26
msgid "Important"
msgstr ""
#: taiga/projects/translations.py:27
msgid "In progress"
msgstr ""
#: taiga/projects/translations.py:28
msgid "Low"
msgstr ""
#: taiga/projects/translations.py:29
msgid "Minor"
msgstr ""
#. Translators: Description of scrum project template.
#: taiga/projects/translations.py:30
msgid "Needs Info"
msgid ""
"The agile product backlog in Scrum is a prioritized features list, "
"containing short descriptions of all functionality desired in the product. "
"When applying Scrum, it's not necessary to start a project with a lengthy, "
"upfront effort to document all requirements. The Scrum product backlog is "
"then allowed to grow and change as more is learned about the product and its "
"customers"
msgstr ""
#: taiga/projects/translations.py:31
#. Translators: Name of kanban project template.
#: taiga/projects/translations.py:33
msgid "Kanban"
msgstr ""
#. Translators: Description of kanban project template.
#: taiga/projects/translations.py:35
msgid ""
"Kanban is a method for managing knowledge work with an emphasis on just-in-"
"time delivery while not overloading the team members. In this approach, the "
"process, from definition of a task to its delivery to the customer, is "
"displayed for participants to see and team members pull work from a queue."
msgstr ""
#. Translators: User story point value (value = undefined)
#: taiga/projects/translations.py:43
msgid "?"
msgstr ""
#. Translators: User story point value (value = 0)
#: taiga/projects/translations.py:45
msgid "0"
msgstr ""
#. Translators: User story point value (value = 0.5)
#: taiga/projects/translations.py:47
msgid "1/2"
msgstr ""
#. Translators: User story point value (value = 1)
#: taiga/projects/translations.py:49
msgid "1"
msgstr ""
#. Translators: User story point value (value = 2)
#: taiga/projects/translations.py:51
msgid "2"
msgstr ""
#. Translators: User story point value (value = 3)
#: taiga/projects/translations.py:53
msgid "3"
msgstr ""
#. Translators: User story point value (value = 5)
#: taiga/projects/translations.py:55
msgid "5"
msgstr ""
#. Translators: User story point value (value = 8)
#: taiga/projects/translations.py:57
msgid "8"
msgstr ""
#. Translators: User story point value (value = 10)
#: taiga/projects/translations.py:59
msgid "10"
msgstr ""
#. Translators: User story point value (value = 15)
#: taiga/projects/translations.py:61
msgid "15"
msgstr ""
#. Translators: User story point value (value = 20)
#: taiga/projects/translations.py:63
msgid "20"
msgstr ""
#. Translators: User story point value (value = 40)
#: taiga/projects/translations.py:65
msgid "40"
msgstr ""
#. Translators: User story status
#. Translators: Task status
#. Translators: Issue status
#: taiga/projects/translations.py:73 taiga/projects/translations.py:96
#: taiga/projects/translations.py:112
msgid "New"
msgstr ""
#: taiga/projects/translations.py:32
msgid "Normal"
msgstr ""
#: taiga/projects/translations.py:33
msgid "Postponed"
msgstr ""
#: taiga/projects/translations.py:34
msgid "Product Owner"
msgstr ""
#: taiga/projects/translations.py:35
msgid "Question"
msgstr ""
#: taiga/projects/translations.py:36
#. Translators: User story status
#: taiga/projects/translations.py:76
msgid "Ready"
msgstr ""
#: taiga/projects/translations.py:37
#. Translators: User story status
#. Translators: Task status
#. Translators: Issue status
#: taiga/projects/translations.py:79 taiga/projects/translations.py:98
#: taiga/projects/translations.py:114
msgid "In progress"
msgstr ""
#. Translators: User story status
#. Translators: Task status
#. Translators: Issue status
#: taiga/projects/translations.py:82 taiga/projects/translations.py:100
#: taiga/projects/translations.py:116
msgid "Ready for test"
msgstr ""
#: taiga/projects/translations.py:38
#. Translators: User story status
#: taiga/projects/translations.py:85
msgid "Done"
msgstr ""
#. Translators: User story status
#: taiga/projects/translations.py:88
msgid "Archived"
msgstr ""
#. Translators: Task status
#. Translators: Issue status
#: taiga/projects/translations.py:102 taiga/projects/translations.py:118
msgid "Closed"
msgstr ""
#. Translators: Task status
#. Translators: Issue status
#: taiga/projects/translations.py:104 taiga/projects/translations.py:120
msgid "Needs Info"
msgstr ""
#. Translators: Issue status
#: taiga/projects/translations.py:122
msgid "Postponed"
msgstr ""
#. Translators: Issue status
#: taiga/projects/translations.py:124
msgid "Rejected"
msgstr ""
#: taiga/projects/translations.py:39
msgid "Stakeholder"
#. Translators: Issue type
#: taiga/projects/translations.py:132
msgid "Bug"
msgstr ""
#: taiga/projects/translations.py:40
#. Translators: Issue type
#: taiga/projects/translations.py:134
msgid "Question"
msgstr ""
#. Translators: Issue type
#: taiga/projects/translations.py:136
msgid "Enhancement"
msgstr ""
#. Translators: Issue priority
#: taiga/projects/translations.py:144
msgid "Low"
msgstr ""
#. Translators: Issue priority
#. Translators: Issue severity
#: taiga/projects/translations.py:146 taiga/projects/translations.py:159
msgid "Normal"
msgstr ""
#. Translators: Issue priority
#: taiga/projects/translations.py:148
msgid "High"
msgstr ""
#. Translators: Issue severity
#: taiga/projects/translations.py:155
msgid "Wishlist"
msgstr ""
#. Translators: Issue severity
#: taiga/projects/translations.py:157
msgid "Minor"
msgstr ""
#. Translators: Issue severity
#: taiga/projects/translations.py:161
msgid "Important"
msgstr ""
#. Translators: Issue severity
#: taiga/projects/translations.py:163
msgid "Critical"
msgstr ""
#. Translators: User role
#: taiga/projects/translations.py:170
msgid "UX"
msgstr ""
#: taiga/projects/translations.py:41
msgid "Wishlist"
#. Translators: User role
#: taiga/projects/translations.py:172
msgid "Design"
msgstr ""
#. Translators: User role
#: taiga/projects/translations.py:174
msgid "Front"
msgstr ""
#. Translators: User role
#: taiga/projects/translations.py:176
msgid "Back"
msgstr ""
#. Translators: User role
#: taiga/projects/translations.py:178
msgid "Product Owner"
msgstr ""
#. Translators: User role
#: taiga/projects/translations.py:180
msgid "Stakeholder"
msgstr ""
#: taiga/projects/userstories/api.py:170

View File

@ -15,20 +15,19 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from taiga.base.api import serializers
from taiga.base.fields import JsonField
from taiga.base.fields import JsonField, I18NJsonField
from . import models
HISTORY_ENTRY_I18N_FIELDS=("points", "status", "severity", "priority", "type")
class HistoryEntrySerializer(serializers.ModelSerializer):
diff = JsonField()
snapshot = JsonField()
values = JsonField()
values_diff = JsonField()
values = I18NJsonField(i18n_fields=HISTORY_ENTRY_I18N_FIELDS)
values_diff = I18NJsonField(i18n_fields=HISTORY_ENTRY_I18N_FIELDS)
user = JsonField()
delete_comment_user = JsonField()
class Meta:
model = models.HistoryEntry

View File

@ -47,6 +47,7 @@ from .custom_attributes.serializers import IssueCustomAttributeSerializer
class PointsSerializer(serializers.ModelSerializer):
class Meta:
model = models.Points
i18n_fields = ("name",)
def validate_name(self, attrs, source):
"""
@ -67,8 +68,10 @@ class PointsSerializer(serializers.ModelSerializer):
class UserStoryStatusSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserStoryStatus
i18n_fields = ("name",)
def validate_name(self, attrs, source):
"""
@ -93,6 +96,7 @@ class UserStoryStatusSerializer(serializers.ModelSerializer):
class TaskStatusSerializer(serializers.ModelSerializer):
class Meta:
model = models.TaskStatus
i18n_fields = ("name",)
def validate_name(self, attrs, source):
"""
@ -115,16 +119,19 @@ class TaskStatusSerializer(serializers.ModelSerializer):
class SeveritySerializer(serializers.ModelSerializer):
class Meta:
model = models.Severity
i18n_fields = ("name",)
class PrioritySerializer(serializers.ModelSerializer):
class Meta:
model = models.Priority
i18n_fields = ("name",)
class IssueStatusSerializer(serializers.ModelSerializer):
class Meta:
model = models.IssueStatus
i18n_fields = ("name",)
def validate_name(self, attrs, source):
"""
@ -147,6 +154,7 @@ class IssueStatusSerializer(serializers.ModelSerializer):
class IssueTypeSerializer(serializers.ModelSerializer):
class Meta:
model = models.IssueType
i18n_fields = ("name",)
######################################################
@ -380,3 +388,4 @@ class ProjectTemplateSerializer(serializers.ModelSerializer):
class Meta:
model = models.ProjectTemplate
read_only_fields = ("created_date", "modified_date")
i18n_fields = ("name", "description")

View File

@ -0,0 +1,180 @@
# Copyright (C) 2015 Andrey Antukh <niwi@niwi.be>
# Copyright (C) 2015 Jesús Espino <jespinog@gmail.com>
# Copyright (C) 2015 David Barragán <bameda@dbarragan.com>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# NOTE: This file is useful to translate default projects templates. Remember update
# when taiga/projects/fixtures/initial_project_templates.json change.
from django.utils.translation import ugettext as _
##########################
## Default template information
##########################
# Translators: Name of scrum project template.
_("Scrum")
# Translators: Description of scrum project template.
_("The agile product backlog in Scrum is a prioritized features list, containing short descriptions of all functionality desired in the product. When applying Scrum, it's not necessary to start a project with a lengthy, upfront effort to document all requirements. The Scrum product backlog is then allowed to grow and change as more is learned about the product and its customers")
# Translators: Name of kanban project template.
_("Kanban")
# Translators: Description of kanban project template.
_("Kanban is a method for managing knowledge work with an emphasis on just-in-time delivery while not overloading the team members. In this approach, the process, from definition of a task to its delivery to the customer, is displayed for participants to see and team members pull work from a queue.")
##########################
## US Points
##########################
# Translators: User story point value (value = undefined)
_("?")
# Translators: User story point value (value = 0)
_("0")
# Translators: User story point value (value = 0.5)
_("1/2")
# Translators: User story point value (value = 1)
_("1")
# Translators: User story point value (value = 2)
_("2")
# Translators: User story point value (value = 3)
_("3")
# Translators: User story point value (value = 5)
_("5")
# Translators: User story point value (value = 8)
_("8")
# Translators: User story point value (value = 10)
_("10")
# Translators: User story point value (value = 15)
_("15")
# Translators: User story point value (value = 20)
_("20")
# Translators: User story point value (value = 40)
_("40")
##########################
## US Statuses
##########################
# Translators: User story status
_("New")
# Translators: User story status
_("Ready")
# Translators: User story status
_("In progress")
# Translators: User story status
_("Ready for test")
# Translators: User story status
_("Done")
# Translators: User story status
_("Archived")
##########################
## Task Statuses
##########################
# Translators: Task status
_("New")
# Translators: Task status
_("In progress")
# Translators: Task status
_("Ready for test")
# Translators: Task status
_("Closed")
# Translators: Task status
_("Needs Info")
##########################
## Issue Statuses
##########################
# Translators: Issue status
_("New")
# Translators: Issue status
_("In progress")
# Translators: Issue status
_("Ready for test")
# Translators: Issue status
_("Closed")
# Translators: Issue status
_("Needs Info")
# Translators: Issue status
_("Postponed")
# Translators: Issue status
_("Rejected")
##########################
## Issue Statuses
##########################
# Translators: Issue type
_("Bug")
# Translators: Issue type
_("Question")
# Translators: Issue type
_("Enhancement")
##########################
## Priorities
##########################
# Translators: Issue priority
_("Low")
# Translators: Issue priority
_("Normal")
# Translators: Issue priority
_("High")
##########################
## Severities
##########################
# Translators: Issue severity
_("Wishlist")
# Translators: Issue severity
_("Minor")
# Translators: Issue severity
_("Normal")
# Translators: Issue severity
_("Important")
# Translators: Issue severity
_("Critical")
##########################
## Roles
##########################
# Translators: User role
_("UX")
# Translators: User role
_("Design")
# Translators: User role
_("Front")
# Translators: User role
_("Back")
# Translators: User role
_("Product Owner")
# Translators: User role
_("Stakeholder")

View File

@ -72,6 +72,7 @@ def test_user_update(client, data):
user_data = UserSerializer(data.registered_user).data
user_data["full_name"] = "test"
user_data = json.dumps(user_data)
results = helper_test_http_method(client, 'put', url, user_data, users)
assert results == [401, 200, 403, 200]