Add plural to language

This commit is contained in:
Cédric Krier committed 2024-10-16 22:46:26 +02:00
1 parent ccd026c9c6
commit 01e715bb05
9 files changed
+120

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
* Add plural to language
* Set Decimal precision of default context from TRYTOND_DECIMAL_PREC
* Replace usage of docstring of Model by __string__ attribute
* Rename ir.model.field 'field_description' into 'string'
+1
View File
@@ -141,6 +141,7 @@ setup(name=name,
'python-dateutil',
'polib',
'python-sql >= 1.5',
'simpleeval',
'werkzeug >= 0.12',
'passlib >= 1.7.0',
'pytz;python_version<"3.9"',
+2
View File
@@ -4,6 +4,7 @@
from .lang import DateError as LanguageDateError
from .lang import DeleteDefaultError as LanguageDeleteDefaultError
from .lang import GroupingError as LanguageGroupingError
from .lang import PluralError as LanguagePluralError
from .lang import TranslatableError as LanguageTranslatableError
from .module import DeactivateDependencyError
from .sequence import AffixError as SequenceAffixError
@@ -16,6 +17,7 @@ __all__ = [
LanguageDateError,
LanguageDeleteDefaultError,
LanguageGroupingError,
LanguagePluralError,
LanguageTranslatableError,
SequenceAffixError,
SequenceMissingError,
+2
View File
@@ -10,6 +10,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_en">
<field name="code">en</field>
<field name="name">English</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%m/%d/%Y</field>
<field name="am">AM</field>
<field name="pm">PM</field>
+46
View File
@@ -7,6 +7,7 @@ from decimal import Decimal
from itertools import takewhile
from locale import CHAR_MAX
from simpleeval import simple_eval
from sql import Table
from trytond.cache import Cache
@@ -31,6 +32,10 @@ class DateError(UserError):
pass
class PluralError(UserError):
pass
class TranslatableError(UserError):
pass
@@ -75,6 +80,16 @@ class Lang(DeactivableMixin, ModelSQL, ModelView):
('rtl', 'Right-to-left'),
], 'Direction', required=True)
nplurals = fields.Integer(
"Number of plurals", required=True,
domain=[
('nplurals', '>=', 1),
('nplurals', '<', 5),
])
plural = fields.Char(
"Plural", required=True,
help="Python expression that returns the plural form for 'n'.")
# date
date = fields.Char("Date", required=True, strip=False)
@@ -171,6 +186,14 @@ class Lang(DeactivableMixin, ModelSQL, ModelView):
def default_direction():
return 'ltr'
@classmethod
def default_nplurals(cls):
return 2
@classmethod
def default_plural(cls):
return 'n != 1'
@staticmethod
def default_date():
return '%m/%d/%Y'
@@ -268,6 +291,7 @@ class Lang(DeactivableMixin, ModelSQL, ModelView):
cls.check_grouping(languages, field_names)
cls.check_date(languages, field_names)
cls.check_translatable(languages)
cls.check_plural(languages, field_names)
@classmethod
def check_grouping(cls, langs, fields_names=None):
@@ -339,6 +363,28 @@ class Lang(DeactivableMixin, ModelSQL, ModelView):
gettext('ir.msg_language_default_translatable',
language=lang.rec_name))
@classmethod
def check_plural(cls, languages, field_names=None):
if field_names and 'plural' not in field_names:
return
for language in languages:
language.get_plural(1)
def get_plural(self, n):
try:
plural = simple_eval(self.plural, names={'n': n})
if not (0 <= plural < self.nplurals):
raise ValueError(
f"result is not between 0 and {self.nplurals}")
return int(plural)
except Exception as exception:
raise PluralError(
gettext('ir.msg_language_plural_invalid',
language=self.rec_name,
plural=self.plural,
n=n,
exception=exception)) from exception
@classmethod
def check_xml_record(cls, langs, values):
pass
+48
View File
@@ -11,6 +11,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_bg">
<field name="code">bg</field>
<field name="name">Bulgarian</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%d.%m.%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -32,6 +34,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_ca">
<field name="code">ca</field>
<field name="name">Català</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%d/%m/%Y</field>
<field name="am">a. m.</field>
<field name="pm">p. m.</field>
@@ -53,6 +57,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_cs">
<field name="code">cs</field>
<field name="name">Czech</field>
<field name="nplurals" eval="3"/>
<field name="plural">0 if n == 1 else 1 if n &gt;= 2 and n &lt;= 4 else 2</field>
<field name="date">%d.%m.%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -74,6 +80,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_de">
<field name="code">de</field>
<field name="name">German</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%d.%m.%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -98,6 +106,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_es">
<field name="code">es</field>
<field name="name">Spanish</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%d/%m/%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -119,6 +129,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_es_419">
<field name="code">es_419</field>
<field name="name">Spanish (Latin American)</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%d/%m/%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -140,6 +152,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_et">
<field name="code">et</field>
<field name="name">Estonian</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%d.%m.%Y</field>
<field name="grouping">[3, 3]</field>
<field name="decimal_point">,</field>
@@ -159,6 +173,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_fa">
<field name="code">fa</field>
<field name="name">Persian</field>
<field name="nplurals" eval="2"/>
<field name="plural">n &gt; 1</field>
<field name="direction">rtl</field>
<field name="date">%Y/%m/%d</field>
<field name="am"></field>
@@ -181,6 +197,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_fi">
<field name="code">fi</field>
<field name="name">Finnish</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%d.%m.%Y</field>
<field name="grouping">[3, 3, 0]</field>
<field name="decimal_point">,</field>
@@ -200,6 +218,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_fr">
<field name="code">fr</field>
<field name="name">French</field>
<field name="nplurals" eval="2"/>
<field name="plural">n &gt; 1</field>
<field name="date">%d.%m.%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -221,6 +241,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_hu">
<field name="code">hu</field>
<field name="name">Hungarian</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%Y-%m-%d</field>
<field name="am"></field>
<field name="pm"></field>
@@ -242,6 +264,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_id">
<field name="code">id</field>
<field name="name">Indonesian</field>
<field name="nplurals" eval="1"/>
<field name="plural">0</field>
<field name="date">%d/%m/%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -263,6 +287,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_it">
<field name="code">it</field>
<field name="name">Italian</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%d/%m/%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -284,6 +310,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_lo">
<field name="code">lo</field>
<field name="name">Lao</field>
<field name="nplurals" eval="1"/>
<field name="plural">0</field>
<field name="date">%d/%m/%Y</field>
<field name="am">AM</field>
<field name="pm">PM</field>
@@ -305,6 +333,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_lt">
<field name="code">lt</field>
<field name="name">Lithuanian</field>
<field name="nplurals" eval="3"/>
<field name="plural">0 if n % 10 == 1 and n % 100 != 11 else 1 if n % 10 >= 2 and (n % 100 &lt; 10 or n % 100 &gt;= 20) else 2</field>
<field name="date">%Y-%m-%d</field>
<field name="am"></field>
<field name="pm"></field>
@@ -326,6 +356,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_nl">
<field name="code">nl</field>
<field name="name">Dutch</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%d-%m-%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -347,6 +379,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_pl">
<field name="code">pl</field>
<field name="name">Polish</field>
<field name="nplurals" eval="3"/>
<field name="plural">0 if n == 1 else 1 if n % 10 &gt;= 2 and n % 10 &lt;= 4 and (n % 100 &lt; 10 or n % 100 &gt;= 20) else 2</field>
<field name="date">%d.%m.%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -368,6 +402,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_pt">
<field name="code">pt</field>
<field name="name">Portuguese</field>
<field name="nplurals" eval="2"/>
<field name="plural">n != 1</field>
<field name="date">%d-%m-%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -389,6 +425,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_ro">
<field name="code">ro</field>
<field name="name">Romanian</field>
<field name="nplurals" eval="3"/>
<field name="plural">0 if n == 1 else 1 if n == 0 or (n % 100 &gt; 0 and n % 100 &lt; 20) else 2</field>
<field name="date">%d.%m.%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -410,6 +448,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_ru">
<field name="code">ru</field>
<field name="name">Russian</field>
<field name="nplurals" eval="3"/>
<field name="plural">0 if n % 10 == 1 and n % 100 != 11 else 1 if n % 10 &gt;= 2 and n % 10 &lt;= 4 and (n % 100 &lt; 10 or n % 100 &gt;= 20) else 2</field>
<field name="date">%d.%m.%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -431,6 +471,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_sl">
<field name="code">sl</field>
<field name="name">Slovenian</field>
<field name="nplurals" eval="4"/>
<field name="plural">0 if n % 100 == 1 else 1 if n % 100 == 2 else 2 if n % 100 == 3 or n % 100 == 4 else 3</field>
<field name="date">%d.%m.%Y</field>
<field name="am"></field>
<field name="pm"></field>
@@ -452,6 +494,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_tr">
<field name="code">tr</field>
<field name="name">Turkish</field>
<field name="nplurals" eval="2"/>
<field name="plural">n &gt; 1</field>
<field name="date">%d-%m-%Y</field>
<field name="grouping">[3, 3, 0]</field>
<field name="decimal_point">,</field>
@@ -471,6 +515,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_uk">
<field name="code">uk</field>
<field name="name">Ukrainian</field>
<field name="nplurals" eval="3"/>
<field name="plural">0 if n % 10 == 1 and n % 100 != 11 else 1 if n % 10 &gt;= 2 and n % 10 &lt;= 4 and (n % 100 &lt; 10 or n % 100 &gt;= 20) else 2</field>
<field name="date">%d.%m.%Y</field>
<field name="grouping">[3, 3]</field>
<field name="decimal_point">,</field>
@@ -490,6 +536,8 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.lang" id="lang_zh_CN">
<field name="code">zh_CN</field>
<field name="name">Chinese Simplified</field>
<field name="nplurals" eval="1"/>
<field name="plural">0</field>
<field name="date">%Y-%m-%d</field>
<field name="am">上午</field>
<field name="pm">下午</field>
+3
View File
@@ -307,6 +307,9 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.message" id="msg_language_invalid_date">
<field name="text">Invalid date format "%(format)s" for language "%(language)s".</field>
</record>
<record model="ir.message" id="msg_language_plural_invalid">
<field name="text">Invalid plural "%(plural)s" for language "%(language)s" with exception "%(exception)s" and n %(n)r.</field>
</record>
<record model="ir.message" id="msg_language_default_translatable">
<field name="text">The default language "%(language)s" must be translatable.</field>
</record>
+6
View File
@@ -14,6 +14,12 @@ this repository contains the full copyright notices and license terms. -->
<field name="translatable"/>
<label name="parent"/>
<field name="parent"/>
<label name="nplurals"/>
<field name="nplurals"/>
<label name="plural"/>
<field name="plural" colspan="4"/>
<separator string="Date Formatting" colspan="6" id="date"/>
<label name="date"/>
<field name="date"/>
+11
View File
@@ -335,6 +335,17 @@ class IrTestCase(ModuleTestCase):
lang.format_number_symbol(value, unit, digits, grouping),
result)
@with_transaction()
def test_lang_plural(self):
"Test Lang plural"
pool = Pool()
Lang = pool.get('ir.lang')
languages = Lang.search([])
for i in range(100):
for language in languages:
language.get_plural(i)
@with_transaction()
def test_model_data_get_id(self):
"Test ModelData.get_id"