Update nereid to use the locale instead of lang #65

This patch makes a significant shift in the way nereid handles
multi language sites. Previously, the language code was used in the
URL, but now a locale code which can be defined by the user is used
This commit is contained in:
resteve 2013-11-19 15:44:04 +01:00
parent 1ebee8f025
commit f3e0534579
13 changed files with 209 additions and 93 deletions

View File

@ -4,10 +4,10 @@ from trytond.pool import Pool
from .party import Address, Party, ContactMechanism, NereidUser, Permission, \
UserPermission
from .routing import URLMap, WebSite, URLRule, URLRuleDefaults, \
WebsiteCountry, WebsiteCurrency
from .routing import URLMap, WebSite, WebSiteLocale, URLRule, URLRuleDefaults, \
WebsiteCountry, WebsiteCurrency, WebsiteWebsiteLocale
from .static_file import NereidStaticFolder, NereidStaticFile
from .currency import Currency, Language
from .currency import Currency
from .template import ContextProcessors
@ -20,14 +20,15 @@ def register():
Permission,
UserPermission,
URLMap,
WebSiteLocale,
WebSite,
URLRule,
URLRuleDefaults,
WebsiteCountry,
WebsiteCurrency,
WebsiteWebsiteLocale,
NereidStaticFolder,
NereidStaticFile,
Language,
Currency,
ContextProcessors,
module='nereid', type_='model'

View File

@ -23,13 +23,6 @@
<menuitem name="Configuration" sequence="10"
id="menu_nereid_configuration" parent="menu_nereid" />
<record model="ir.ui.view" id="lang_view_tree">
<field name="model">ir.lang</field>
<field name="type">tree</field>
<field name="inherit" ref="ir.lang_view_tree"/>
<field name="name">lang_form</field>
</record>
<!-- Routing -->
<menuitem name="Routing" id="menu_nereid_routing"
sequence="10" parent="menu_nereid_configuration" />
@ -60,6 +53,34 @@
<menuitem parent="menu_nereid_configuration" action="act_website_form"
id="menu_website_form" sequence="5"/>
<!-- Web Site Locale -->
<record model="ir.ui.view" id="website_locale_view_form">
<field name="model">nereid.website.locale</field>
<field name="type">form</field>
<field name="name">website_locale_form</field>
</record>
<record model="ir.ui.view" id="website_locale_view_tree">
<field name="model">nereid.website.locale</field>
<field name="type">tree</field>
<field name="name">website_locale_tree</field>
</record>
<record model="ir.action.act_window" id="act_website_locale_form">
<field name="name">Web Sites Locale</field>
<field name="res_model">nereid.website.locale</field>
</record>
<record model="ir.action.act_window.view" id="act_website_locale_form_view1">
<field name="sequence" eval="10" />
<field name="view" ref="website_locale_view_tree" />
<field name="act_window" ref="act_website_locale_form" />
</record>
<record model="ir.action.act_window.view" id="act_website_locale_form_view2">
<field name="sequence" eval="20" />
<field name="view" ref="website_locale_view_form" />
<field name="act_window" ref="act_website_locale_form" />
</record>
<menuitem parent="menu_nereid_configuration" action="act_website_locale_form"
id="menu_website_locale_form" sequence="5"/>
<!-- URL Map -->
<record model="ir.ui.view" id="url_map_view_form">
<field name="model">nereid.url_map</field>

View File

@ -1,9 +1,9 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.model import ModelView, ModelSQL, fields
from trytond.model import ModelView, ModelSQL
from nereid import request
__all__ = ['Currency', 'Language']
__all__ = ['Currency']
class Currency(ModelSQL, ModelView):
@ -34,11 +34,3 @@ class Currency(ModelSQL, ModelView):
'compute': cls.compute,
'convert': cls.convert
}
class Language(ModelSQL, ModelView):
__name__ = "ir.lang"
default_currency = fields.Many2One(
'currency.currency', 'Default Currency'
)

View File

@ -15,8 +15,8 @@ from trytond.pool import Pool
from .i18n import _
__all__ = ['URLMap', 'WebSite', 'URLRule', 'URLRuleDefaults',
'WebsiteCountry', 'WebsiteCurrency']
__all__ = ['URLMap', 'WebSite', 'WebSiteLocale', 'URLRule', 'URLRuleDefaults',
'WebsiteCountry', 'WebsiteCurrency', 'WebsiteWebsiteLocale']
class URLMap(ModelSQL, ModelView):
@ -88,6 +88,28 @@ class LoginForm(Form):
password = PasswordField(_('Password'), [validators.Required()])
class WebSiteLocale(ModelSQL, ModelView):
'Web Site Locale'
__name__ = "nereid.website.locale"
_rec_name = 'code'
code = fields.Char('Code', required=True)
language = fields.Many2One(
'ir.lang', 'Default Language', required=True
)
currency = fields.Many2One(
'currency.currency', 'Currency', ondelete='CASCADE', required=True
)
@classmethod
def __setup__(cls):
super(WebSiteLocale, cls).__setup__()
cls._sql_constraints += [
('unique_code', 'UNIQUE(code)',
'Code must be unique'),
]
class WebSite(ModelSQL, ModelView):
"""
One of the most powerful features of Nereid is the ability to
@ -132,12 +154,17 @@ class WebSite(ModelSQL, ModelView):
'nereid.website-currency.currency',
'website', 'currency', 'Currencies Available')
#: Default language
default_language = fields.Many2One(
'ir.lang', 'Default Language',
#: Default locale
default_locale = fields.Many2One(
'nereid.website.locale', 'Default Locale',
required=True
)
#: Allowed locales in the website
locales = fields.Many2Many(
'nereid.website-nereid.website.locale',
'website', 'locale', 'Languages Available')
#: The res.user with which the nereid application will be loaded
#: .. versionadded: 0.3
application_user = fields.Many2One(
@ -497,3 +524,16 @@ class WebsiteCurrency(ModelSQL):
currency = fields.Many2One(
'currency.currency', 'Currency',
ondelete='CASCADE', select=1, required=True)
class WebsiteWebsiteLocale(ModelSQL):
"Languages to be made available on website"
__name__ = 'nereid.website-nereid.website.locale'
_table = 'website_locale_rel'
website = fields.Many2One(
'nereid.website', 'Website',
ondelete='CASCADE', select=1, required=True)
locale = fields.Many2One(
'nereid.website.locale', 'Locale',
ondelete='CASCADE', select=1, required=True)

View File

@ -26,6 +26,7 @@ class TestAddress(NereidTestCase):
trytond.tests.test_tryton.install_module('nereid')
self.nereid_website_obj = POOL.get('nereid.website')
self.nereid_website_locale_obj = POOL.get('nereid.website.locale')
self.nereid_user_obj = POOL.get('nereid.user')
self.url_map_obj = POOL.get('nereid.url_map')
self.company_obj = POOL.get('company.company')
@ -130,12 +131,19 @@ class TestAddress(NereidTestCase):
url_map_id, = self.url_map_obj.search([], limit=1)
en_us, = self.language_obj.search([('code', '=', 'en_US')])
currency, = self.currency_obj.search([('code', '=', 'USD')])
locale, = self.nereid_website_locale_obj.create([{
'code': 'en_US',
'language': en_us,
'currency': currency,
}])
self.nereid_website_obj.create([{
'name': 'localhost',
'url_map': url_map_id,
'company': self.company,
'application_user': USER,
'default_language': en_us,
'default_locale': locale,
'locales': [('add', [locale.id])],
'guest_user': self.guest_user,
'countries': [('set', self.available_countries)],
}])
@ -162,8 +170,8 @@ class TestAddress(NereidTestCase):
'streetbis': 'StreetBis',
'zip': 'zip',
'city': 'City',
#~ 'email': 'email@example.com',
#~ 'phone': '1234567890',
'email': 'email@example.com',
'phone': '1234567890',
'country': self.available_countries[0].id,
'subdivision': self.country_obj(
self.available_countries[0]).subdivisions[0].id,
@ -205,8 +213,8 @@ class TestAddress(NereidTestCase):
self.assertEqual(address.streetbis, address_data['streetbis'])
self.assertEqual(address.zip, address_data['zip'])
self.assertEqual(address.city, address_data['city'])
#~ self.assertEqual(address.email, address_data['email'])
#~ self.assertEqual(address.phone, address_data['phone'])
self.assertEqual(address.email, address_data['email'])
self.assertEqual(address.phone, address_data['phone'])
self.assertEqual(address.country.id, address_data['country'])
self.assertEqual(
address.subdivision.id, address_data['subdivision']
@ -227,8 +235,8 @@ class TestAddress(NereidTestCase):
'streetbis': 'StreetBis',
'zip': 'zip',
'city': 'City',
#~ 'email': 'email@example.com',
#~ 'phone': '1234567890',
'email': 'email@example.com',
'phone': '1234567890',
'country': self.available_countries[0].id,
'subdivision': self.country_obj(
self.available_countries[0]).subdivisions[0].id,
@ -271,8 +279,8 @@ class TestAddress(NereidTestCase):
self.assertEqual(address.streetbis, address_data['streetbis'])
self.assertEqual(address.zip, address_data['zip'])
self.assertEqual(address.city, address_data['city'])
#~ self.assertEqual(address.email, address_data['email'])
#~ self.assertEqual(address.phone, address_data['phone'])
self.assertEqual(address.email, address_data['email'])
self.assertEqual(address.phone, address_data['phone'])
self.assertEqual(address.country.id, address_data['country'])
self.assertEqual(
address.subdivision.id, address_data['subdivision']

View File

@ -25,6 +25,7 @@ class TestAuth(NereidTestCase):
trytond.tests.test_tryton.install_module('nereid')
self.nereid_website_obj = POOL.get('nereid.website')
self.nereid_website_locale_obj = POOL.get('nereid.website.locale')
self.nereid_permission_obj = POOL.get('nereid.permission')
self.nereid_user_obj = POOL.get('nereid.user')
self.url_map_obj = POOL.get('nereid.url_map')
@ -71,12 +72,19 @@ class TestAuth(NereidTestCase):
url_map, = self.url_map_obj.search([], limit=1)
en_us, = self.language_obj.search([('code', '=', 'en_US')])
currency, = self.currency_obj.search([('code', '=', 'USD')])
locale, = self.nereid_website_locale_obj.create([{
'code': 'en_US',
'language': en_us,
'currency': currency,
}])
self.nereid_website_obj.create([{
'name': 'localhost',
'url_map': url_map,
'company': self.company,
'application_user': USER,
'default_language': en_us,
'default_locale': locale,
'locales': [('add', [locale.id])],
'guest_user': self.guest_user,
}])
self.templates = {

View File

@ -19,6 +19,7 @@ class TestCurrency(NereidTestCase):
trytond.tests.test_tryton.install_module('nereid')
self.nereid_website_obj = POOL.get('nereid.website')
self.nereid_website_locale_obj = POOL.get('nereid.website.locale')
self.nereid_permission_obj = POOL.get('nereid.permission')
self.nereid_user_obj = POOL.get('nereid.user')
self.url_map_obj = POOL.get('nereid.url_map')
@ -37,6 +38,12 @@ class TestCurrency(NereidTestCase):
'symbol': '$',
'rates': [('create', [{'rate': Decimal('1')}])],
}])
eur, = self.currency_obj.create([{
'name': 'Euro',
'code': 'EUR',
'symbol': 'E',
'rates': [('create', [{'rate': Decimal('2')}])],
}])
self.party, = self.party_obj.create([{
'name': 'Openlabs',
}])
@ -82,12 +89,25 @@ class TestCurrency(NereidTestCase):
self.website_currencies = [c1, c2]
url_map, = self.url_map_obj.search([], limit=1)
self.en_us, = self.language_obj.search([('code', '=', 'en_US')])
self.es_es, = self.language_obj.search([('code', '=', 'es_ES')])
self.usd, = self.currency_obj.search([('code', '=', 'USD')])
self.eur, = self.currency_obj.search([('code', '=', 'EUR')])
locale_en_us, locale_es_es = self.nereid_website_locale_obj.create([{
'code': 'en_US',
'language': self.en_us,
'currency': self.usd,
}, {
'code': 'es_ES',
'language': self.es_es,
'currency': self.eur,
}])
self.nereid_website_obj.create([{
'name': 'localhost',
'url_map': url_map,
'company': self.company,
'application_user': USER,
'default_language': self.en_us,
'default_locale': locale_en_us.id,
'locales': [('add', [locale_en_us.id, locale_es_es.id])],
'guest_user': self.guest_user.id,
'currencies': [('set', self.website_currencies)],
}])
@ -111,37 +131,41 @@ class TestCurrency(NereidTestCase):
app = self.get_app()
with app.test_client() as c:
rv = c.get('/en_US/')
rv = c.get('/en_us/')
self.assertEqual(rv.status_code, 200)
self.assertEqual(int(rv.data), self.company.currency.id)
with app.test_request_context('/en_us/'):
self.assertEqual(
self.currency_obj.convert(Decimal('100')), Decimal('100')
)
def test_0020_currency_from_locale(self):
"""
Test and ensure that the currency is based on the locale
"""
with Transaction().start(DB_NAME, USER, CONTEXT):
self.setup_defaults()
app = self.get_app()
with app.test_client() as c:
rv = c.get('/en_US/')
self.assertEqual(rv.status_code, 200)
self.assertEqual(int(rv.data), int(self.usd.id))
rv = c.get('/es_ES/')
self.assertEqual(rv.status_code, 200)
self.assertEqual(int(rv.data), int(self.eur.id))
with app.test_request_context('/en_US/'):
self.assertEqual(
self.currency_obj.convert(Decimal('100')), Decimal('100')
)
def test_0020_currency_from_language(self):
"""
Set the currency for the language and check if the currency
in the request is correct
"""
with Transaction().start(DB_NAME, USER, CONTEXT):
self.setup_defaults()
app = self.get_app()
self.language_obj.write(
[self.en_us], {'default_currency': self.lang_currency}
)
with app.test_client() as c:
rv = c.get('/en_US/')
self.assertEqual(rv.status_code, 200)
self.assertEqual(int(rv.data), int(self.lang_currency))
with app.test_request_context('/en_US/'):
with app.test_request_context('/es_ES/'):
self.assertEqual(
self.currency_obj.convert(Decimal('100')), Decimal('3000')
self.currency_obj.convert(Decimal('100')), Decimal('200')
)

View File

@ -25,6 +25,7 @@ class TestI18N(NereidTestCase):
trytond.tests.test_tryton.install_module('nereid')
self.nereid_website_obj = POOL.get('nereid.website')
self.nereid_website_locale_obj = POOL.get('nereid.website.locale')
self.nereid_permission_obj = POOL.get('nereid.permission')
self.nereid_user_obj = POOL.get('nereid.user')
self.url_map_obj = POOL.get('nereid.url_map')
@ -55,12 +56,19 @@ class TestI18N(NereidTestCase):
})
url_map_id, = self.url_map_obj.search([], limit=1)
en_us, = self.language_obj.search([('code', '=', 'en_US')])
currency, = self.currency_obj.search([('code', '=', 'USD')])
locale, = self.nereid_website_locale_obj.create([{
'code': 'en_US',
'language': en_us,
'currency': currency,
}])
self.nereid_website_obj.create({
'name': 'localhost',
'url_map': url_map_id,
'company': self.company_id,
'application_user': USER,
'default_language': en_us,
'default_locale': locale,
'locales': [('add', [locale.id])],
'guest_user': self.guest_user_id,
})

View File

@ -34,6 +34,7 @@ class TestStaticFile(NereidTestCase):
trytond.tests.test_tryton.install_module('nereid')
self.nereid_website_obj = POOL.get('nereid.website')
self.nereid_website_locale_obj = POOL.get('nereid.website.locale')
self.nereid_user_obj = POOL.get('nereid.user')
self.url_map_obj = POOL.get('nereid.url_map')
self.company_obj = POOL.get('company.company')
@ -84,12 +85,19 @@ class TestStaticFile(NereidTestCase):
url_map_id, = self.url_map_obj.search([], limit=1)
en_us, = self.language_obj.search([('code', '=', 'en_US')])
currency, = self.currency_obj.search([('code', '=', 'USD')])
locale, = self.nereid_website_locale_obj.create([{
'code': 'en_US',
'language': en_us,
'currency': currency,
}])
self.nereid_website_obj.create([{
'name': 'localhost',
'url_map': url_map_id,
'company': self.company,
'application_user': USER,
'default_language': en_us,
'default_locale': locale,
'locales': [('add', [locale.id])],
'guest_user': self.guest_user,
}])

View File

@ -19,16 +19,8 @@
<field name="url_map" ref="default_url_map" />
</record>
<record id="home_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/</field>
<field name="endpoint">nereid.website.home</field>
<field name="sequence" eval="10" />
<field name="http_method_get" eval="True"/>
<field name="url_map" ref="default_url_map" />
</record>
<record id="login_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/login</field>
<field name="rule">/login</field>
<field name="endpoint">nereid.website.login</field>
<field name="sequence" eval="20" />
<field name="http_method_get" eval="True"/>
@ -37,7 +29,7 @@
</record>
<record id="logout_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/logout</field>
<field name="rule">/logout</field>
<field name="endpoint">nereid.website.logout</field>
<field name="sequence" eval="30" />
<field name="http_method_get" eval="True"/>
@ -45,7 +37,7 @@
</record>
<record id="registration_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/registration</field>
<field name="rule">/registration</field>
<field name="endpoint">nereid.user.registration</field>
<field name="sequence" eval="40" />
<field name="http_method_get" eval="True"/>
@ -54,7 +46,7 @@
</record>
<record id="account_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/account</field>
<field name="rule">/account</field>
<field name="endpoint">nereid.website.account</field>
<field name="sequence" eval="50" />
<field name="http_method_get" eval="True"/>
@ -62,7 +54,7 @@
</record>
<record id="change_pass_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/change-password</field>
<field name="rule">/change-password</field>
<field name="endpoint">nereid.user.change_password</field>
<field name="sequence" eval="60" />
<field name="http_method_get" eval="True"/>
@ -71,7 +63,7 @@
</record>
<record id="new_pass_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/new-password</field>
<field name="rule">/new-password</field>
<field name="endpoint">nereid.user.new_password</field>
<field name="sequence" eval="65" />
<field name="http_method_get" eval="True"/>
@ -80,7 +72,7 @@
</record>
<record id="activate_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/activate-account/&lt;int:active_id&gt;/&lt;activation_code&gt;</field>
<field name="rule">/activate-account/&lt;int:active_id&gt;/&lt;activation_code&gt;</field>
<field name="endpoint">nereid.user.activate</field>
<field name="sequence" eval="70" />
<field name="http_method_get" eval="True"/>
@ -89,7 +81,7 @@
</record>
<record id="reset_account_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/reset-account</field>
<field name="rule">/reset-account</field>
<field name="endpoint">nereid.user.reset_account</field>
<field name="sequence" eval="80" />
<field name="http_method_get" eval="True"/>
@ -98,7 +90,7 @@
</record>
<record id="save_address_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/save-new-address</field>
<field name="rule">/save-new-address</field>
<field name="endpoint">party.address.edit_address</field>
<field name="sequence" eval="90" />
<field name="http_method_get" eval="True"/>
@ -108,7 +100,7 @@
<record id="edit_address_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/edit-address/&lt;int:address&gt;</field>
<field name="rule">/edit-address/&lt;int:address&gt;</field>
<field name="endpoint">party.address.edit_address</field>
<field name="sequence" eval="90" />
<field name="http_method_get" eval="True"/>
@ -117,7 +109,7 @@
</record>
<record id="view_address_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/view-address</field>
<field name="rule">/view-address</field>
<field name="endpoint">party.address.view_address</field>
<field name="sequence" eval="100" />
<field name="http_method_get" eval="True"/>
@ -125,7 +117,7 @@
</record>
<record id="countries_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/countries</field>
<field name="rule">/countries</field>
<field name="endpoint">nereid.website.country_list</field>
<field name="sequence" eval="110" />
<field name="http_method_get" eval="True"/>
@ -133,7 +125,7 @@
</record>
<record id="subdivisions_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/subdivisions</field>
<field name="rule">/subdivisions</field>
<field name="endpoint">nereid.website.subdivision_list</field>
<field name="sequence" eval="120" />
<field name="http_method_get" eval="True"/>
@ -141,7 +133,7 @@
</record>
<record id="static_file_url" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/static-file/&lt;folder&gt;/&lt;name&gt;</field>
<field name="rule">/static-file/&lt;folder&gt;/&lt;name&gt;</field>
<field name="endpoint">nereid.static.file.send_static_file</field>
<field name="sequence" eval="130" />
<field name="http_method_get" eval="True"/>
@ -149,14 +141,14 @@
</record>
<record id="user_status" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/user_status</field>
<field name="rule">/user_status</field>
<field name="endpoint">nereid.website.user_status</field>
<field name="sequence" eval="150" />
<field name="url_map" ref="nereid.default_url_map" />
</record>
<record id="add_contact_mechanism" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/contact-mechanisms/add</field>
<field name="rule">/contact-mechanisms/add</field>
<field name="endpoint">party.contact_mechanism.add</field>
<field name="sequence" eval="140" />
<field name="http_method_post" eval="True"/>
@ -164,7 +156,7 @@
</record>
<record id="remove_contact_mechanism" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/contact-mechanisms/remove</field>
<field name="rule">/contact-mechanisms/remove</field>
<field name="endpoint">party.contact_mechanism.remove</field>
<field name="sequence" eval="140" />
<field name="http_method_post" eval="True"/>
@ -172,7 +164,7 @@
</record>
<record id="user_profile" model="nereid.url_rule">
<field name="rule">/&lt;language&gt;/me</field>
<field name="rule">/me</field>
<field name="endpoint">nereid.user.profile</field>
<field name="sequence" eval="300" />
<field name="http_method_get" eval="True"/>

View File

@ -10,8 +10,8 @@ this repository contains the full copyright notices and license terms. -->
<field name="active" />
<label name="company"/>
<field name="company"/>
<label name="default_language"/>
<field name="default_language"/>
<label name="default_locale"/>
<field name="default_locale"/>
<label name="application_user"/>
<field name="application_user"/>
<label name="guest_user"/>
@ -19,6 +19,9 @@ this repository contains the full copyright notices and license terms. -->
<label name="timezone"/>
<field name="timezone"/>
<notebook colspan="4">
<page id="locales" string="Locales">
<field name="locales"/>
</page>
<page id="Countries" string="Countries">
<field name="countries"/>
</page>

View File

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form string="Web Site Locale">
<label name="code"/>
<field name="code"/>
<label name="language"/>
<field name="language"/>
<label name="currency"/>
<field name="currency"/>
</form>

View File

@ -1,8 +1,8 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="/tree/field[@name='active']" position="after">
<field name="default_currency"/>
</xpath>
</data>
<tree string="Web Sites Locale">
<field name="code"/>
<field name="language"/>
<field name="currency"/>
</tree>