plone.app.multilingual/master: Merge pull request #284 from plone/rename_media_to_assets
GitHub <jenkins-z4DKO/[email protected]>
| Newsgroups | gmane.comp.web.zope.plone.cvs |
|---|---|
| Message-ID | <[email protected]> |
Repository: plone.app.multilingual Branch: refs/heads/master Date: 2017-07-09T22:26:31+03:00 Author: Asko Soukka (datakurre) <[email protected]> Commit: https://github.com/plone/plone.app.multilingual/commit/c11bf68e097a21e519e65992081bcb27909f7557 Merge pull request #284 from plone/rename_media_to_assets Rename media to assets Files changed: M CHANGES.rst M README.rst M src/plone/app/multilingual/browser/menu.py M src/plone/app/multilingual/browser/setup.py M src/plone/app/multilingual/tests/test_catalog.py M src/plone/app/multilingual/tests/test_lrf.py M src/plone/app/multilingual/tests/test_sitemap.py M src/plone/app/multilingual/tests/test_subscribers.py diff --git a/CHANGES.rst b/CHANGES.rst index cb02ef9..da791e3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -10,7 +10,9 @@ Breaking changes: New features: -- *add item here* +- Rename ``media`` folder to a more generic name ``assets`` by default and + add i18nize it to be localization aware + [agitator, datakurre] Bug fixes: diff --git a/README.rst b/README.rst index cb0c68a..6265881 100644 --- a/README.rst +++ b/README.rst @@ -4,28 +4,13 @@ Introduction ============ -In the old days before Plone 4.3, talking about multi-language support in Plone -is talk about Products.LinguaPlone. It has been the *defacto* standard for -managing translations of Archetypes-based content types in Plone through the -years. Somehow its functionality never made its way into the Plone core and -today it is in legacy status. Nowadays, Plone faces the rising of Dexterity -content types and its adoption into the core since Plone 4.3. With Plone 5 -released, the transition is completed and Dexterity is shipped as its default -content type story. - -plone.app.multilingual was designed originally to provide Plone a whole -multilingual story. Using ZCA technologies, enables translations to Dexterity -and Archetypes content types as well managed via an unified UI. - -This module provides the user interface for managing content translations. It's -the app package of the next generation Plone multilingual engine. It's designed -to work with Dexterity content types and the *old fashioned* Archetypes based -content types as well. It only works with Plone 4.1 and above due to the use of -UUIDs for referencing the translations. - -After more than 7 years, a GSOC, redesigns, reimplementations due to deprecated -libraries, two major Plone versions finally we are able to say that -plone.app.multilingual is finally here. +In the old days before Plone 4.3, talking about multi-language support in Plone is talk about Products.LinguaPlone. It has been the *defacto* standard for managing translations of Archetypes-based content types in Plone through the years. Somehow its functionality never made its way into the Plone core and today it is in legacy status. Nowadays, Plone faces the rising of Dexterity content types and its adoption into the core since Plone 4.3. With Plone 5 released, the transition is completed and Dexterity is shipped as its default content type story. + +plone.app.multilingual was designed originally to provide Plone a whole multilingual story. Using ZCA technologies, enables translations to Dexterity and Archetypes content types as well managed via an unified UI. + +This module provides the user interface for managing content translations. It's the app package of the next generation Plone multilingual engine. It's designed to work with Dexterity content types and the *old fashioned* Archetypes based content types as well. It only works with Plone 4.1 and above due to the use of UUIDs for referencing the translations. + +After more than 7 years, a GSOC, redesigns, reimplementations due to deprecated libraries, two major Plone versions finally we are able to say that plone.app.multilingual is finally here. Versions @@ -40,6 +25,7 @@ Versions * ``4.x`` - Plone >= 5.x (5.0.3 minimum, due to GenericSetup dependency) + Components ========== @@ -51,179 +37,121 @@ and one optional: * archetypes.multilingual (enables Archetypes support) + Usage ===== -To use this package with both Dexterity and Archetypes based content types you -should add the following line to your *eggs* buildout section:: +To use this package with both Dexterity and Archetypes based content types you should add the following line to your *eggs* buildout section:: eggs = plone.app.multilingual[archetypes] -To use this package with plone.app.contenttypes you should add the following -line to your *eggs* buildout section:: +To use this package with plone.app.contenttypes you should add the following line to your *eggs* buildout section:: eggs = plone.app.multilingual + Setup ===== -After re-running your buildout and installing the newly available add-ons, you -should go to the *Languages* section of your site's control panel and select -at least two or more languages for your site. You will now be able to create -translations of Plone's default content types, or to link existing content as -translations. +After re-running your buildout and installing the newly available add-ons, you should go to the *Languages* section of your site's control panel and select at least two or more languages for your site. You will now be able to create translations of Plone's default content types, or to link existing content as translations. + Features ======== These are the most important features PAM provides. + Root Language folders --------------------- -After the setup, PAM will create root folders for each of your site's -languages and put translated content into the appropriate folders. A language -folder implements INavigationRoot, so from the user's point of view, each -language is "jailed" inside its correspondent language folder. There are event -subscribers in place to capture user interaction with content and update the -language in contents accordingly, for example when user moves or copy content -between language folders. +After the setup, PAM will create root folders for each of your site's languages and put translated content into the appropriate folders. A language folder implements INavigationRoot, so from the user's point of view, each language is "jailed" inside its correspondent language folder. There are event subscribers in place to capture user interaction with content and update the language in contents accordingly, for example when user moves or copy content between language folders. Babel view ---------- -An evolution of the LP *translate* view, unified for either Archetypes and -Dexterity content types. It features an already translated content viewer for -the current content being edited via an ajaxified dynamic selector that shows -them on the fly on user request. +An evolution of the LP *translate* view, unified for either Archetypes and Dexterity content types. It features an already translated content viewer for the current content being edited via an ajaxified dynamic selector that shows them on the fly on user request. Language independent fields --------------------------- -PAM has support for language independent fields, but with a twist respect the -LP implementation. As PAM does design does not give more relevance to one -translated object above the others siblings (has no canonical object), fields -marked as language independent get copied over all the members of the -translation group always. The PAM UI will warn you about this behavior by -reminding you that the values in the field on the other group participants -will be overwritten. +PAM has support for language independent fields, but with a twist respect the LP implementation. As PAM does design does not give more relevance to one translated object above the others siblings (has no canonical object), fields marked as language independent get copied over all the members of the translation group always. The PAM UI will warn you about this behavior by reminding you that the values in the field on the other group participants will be overwritten. Translation locator policy -------------------------- -When translating content, this policy decides how it would be placed in the -site's structure. There are two policies in place: +When translating content, this policy decides how it would be placed in the site's structure. There are two policies in place: - * LP way, the translation gets placed in the nearest translated folder in - parent's hierarchy + * LP way, the translation gets placed in the nearest translated folder in parent's hierarchy - * Ask user where to place the translated element in the destination - language root folder + * Ask user where to place the translated element in the destination language root folder Language selector policy ------------------------ -While browsing the site, the language selector viewlet allows users to switch -site's content language and ease access between translations of the current -content. There are two policies in place in case the translation of a specific -language does not exist (yet): +While browsing the site, the language selector viewlet allows users to switch site's content language and ease access between translations of the current content. There are two policies in place in case the translation of a specific language does not exist (yet): * LP way, the selector shows the nearest translated container. - * Shows the user an informative view that shows the current available - translations for the current content. + * Shows the user an informative view that shows the current available translations for the current content. -The "Media" folder - a shared "Language Independent Folder" ------------------------------------------------------------ +The assets folder - a shared "Language Independent Folder" +---------------------------------------------------------- -The root language folders are used to house the content tree for the -corresponding language. However, there are some use cases where we need -content that does not belong to any language. For example, for assets or side -resources like images, videos and documents. For this reason PAM supplies a -special Language Independent Folder to house these kind of objects. -After PAM setup, there is a special folder called "Media", which can be -accessed through the "Go to shared folder" item of the "Translate" menu. All -items placed in this folder will have neutral as their default language and -will be visible from the other root language folders as if they were placed -there as well. +The root language folders are used to house the content tree for the corresponding language. However, there are some use cases where we need content that does not belong to any language. For example, for assets or side resources like images, videos and documents. For this reason PAM supplies a special Language Independent Folder to house these kind of objects. After PAM setup, there is a special folder called "Assets" (folder title may depend on the language), which can be accessed through the "Go to Assets folder" item of the "Translate" menu. All items placed in this folder will have neutral as their default language and will be visible from the other root language folders as if they were placed there as well. -Note: Language Independent Folder's have also been historically known as -"Neutral root folder", "language neutral folder" and -"language shared (folder)". Also don't confuse Language Independent Folders -with Language Independent Fields +Note: + * Language Independent Folder's have also been historically known as "Neutral root folder", "language neutral folder" and "language shared (folder)". + * Also don't confuse Language Independent Folders with Language Independent Fields + * The Language Independent Folder formerly known as ``Media`` folder, was renamed to the more generic name ``Assets`` (the name may depend on the language). Translation map --------------- -In order to ease the translation tasks, we devised a tool that displays in a -useful way all the current translated objects and its current translation -information. The map also shows a list of missing translations in case you -want to build a *mirrored* (completely) translated site. +In order to ease the translation tasks, we devised a tool that displays in a useful way all the current translated objects and its current translation information. The map also shows a list of missing translations in case you want to build a *mirrored* (completely) translated site. Google Translation Service integration -------------------------------------- -If you are subscriber of the Google Translation service (a paid service), you -can setup your API key on *Languages* site setup. Then, you will notice a new -icon in the babel view that takes the original field on the left side and -using Google Translations service, translates its contents and fill the right -side field. +If you are subscriber of the Google Translation service (a paid service), you can setup your API key on *Languages* site setup. Then, you will notice a new icon in the babel view that takes the original field on the left side and using Google Translations service, translates its contents and fill the right side field. LinguaPlone migration --------------------- -You can migrate your existing LP powered sites to PAM using the *Migration* tab -in the *Languages* control panel. The migration has been divided into 4 steps -for separation of concerns and for improving the success of each of the required -procedures. +You can migrate your existing LP powered sites to PAM using the *Migration* tab in the *Languages* control panel. The migration has been divided into 4 steps for separation of concerns and for improving the success of each of the required procedures. + Step 0 (optional) - Reindex the language index ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The migration of LinguaPlone content depends on an up-to-date Language index. -Use this step to refresh this index. **Warning:** Depending on the number of -items in your site, this can take a considerable amount of time. This step is -not destructive and can be executed as many times as needed. +The migration of LinguaPlone content depends on an up-to-date Language index. Use this step to refresh this index. **Warning:** Depending on the number of items in your site, this can take a considerable amount of time. This step is not destructive and can be executed as many times as needed. + Step 1 - Relocate content to the proper root language folder ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This step will move the site's content to its correspondent root language folder -and previously will make a search for misplaced content through the site's -content tree and will move them to its nearest translated parent. **Warning:** -This step is destructive as it will alter your content tree structure. Make sure -you have previously configured your site's languages properly in the 'Site -Languages' tab of the 'Languages' control panel. It's advisable that you do not -perform this step on production servers having not tried it in -development/preproduction servers previously. Depending on the distribution of -your site's content and the accuracy of the language information on each content -object you may need to relocate manually some misplaced content after this step. -Despite the fact that this step is 'destructive' it can be executed as times as -needed if some problem is detected and afterwards you fix the problem. Please, -refer to the procedure log when it finishes. +This step will move the site's content to its correspondent root language folder and previously will make a search for misplaced content through the site's content tree and will move them to its nearest translated parent. **Warning:** This step is destructive as it will alter your content tree structure. Make sure you have previously configured your site's languages properly in the 'Site Languages' tab of the 'Languages' control panel. It's advisable that you do not perform this step on production servers having not tried it in development/preproduction servers previously. Depending on the distribution of your site's content and the accuracy of the language information on each content object you may need to relocate manually some misplaced content after this step. Despite the fact that th is step is 'destructive' it can be executed as times as needed if some problem is detected and afterwards you fix the problem. Please, refer to the procedure log when it finishes. + Step 2 - Transfer multilingual catalog information ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This step will transfer the relations between translations stored by LinguaPlone -to the PAM catalog. This step is not destructive and can be executed as many -times as needed. +This step will transfer the relations between translations stored by LinguaPlone to the PAM catalog. This step is not destructive and can be executed as many times as needed. + Step 3 - Cleanup after migration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This step will search and fix some lost dependencies to the ITranslatable -interface hidden in the relation catalog and it gets rid of them. It must be run -only when LinguaPlone is already uninstalled, so this step is hidden until then. +This step will search and fix some lost dependencies to the ITranslatable interface hidden in the relation catalog and it gets rid of them. It must be run only when LinguaPlone is already uninstalled, so this step is hidden until then. Marking objects as translatables @@ -232,16 +160,13 @@ Marking objects as translatables Archetypes ---------- -By default, if PAM is installed, Archetypes-based content types are marked as -translatables +By default, if PAM is installed, Archetypes-based content types are marked as translatables Dexterity --------- -Users should mark a dexterity content type as translatable by assigning a the -multilingual behavior to the definition of the content type either via file -system, supermodel or through the web. +Users should mark a dexterity content type as translatable by assigning a the multilingual behavior to the definition of the content type either via file system, supermodel or through the web. Marking fields as language independant @@ -250,8 +175,7 @@ Marking fields as language independant Archetypes ---------- -The language independent fields on Archetype-based content are marked the same -way as in LinguaPlone:: +The language independent fields on Archetype-based content are marked the same way as in LinguaPlone:: atapi.StringField( 'myField', @@ -263,8 +187,7 @@ way as in LinguaPlone:: .. note:: - If you want to completely remove LinguaPlone of your installation, you - should make sure that your code are dependant in any way of LP. + If you want to completely remove LinguaPlone of your installation, you should make sure that your code are dependant in any way of LP. Dexterity @@ -272,6 +195,7 @@ Dexterity There are four ways of achieve it. + Directive ~~~~~~~~~ @@ -280,6 +204,7 @@ In your content type class declaration:: from plone.app.multilingual.dx import directives directives.languageindependent('field') + Supermodel ~~~~~~~~~~ @@ -290,6 +215,7 @@ In your content type XML file declaration:: <title>myField</title> </field> + Native ~~~~~~ @@ -313,8 +239,7 @@ The key points are: 1. Each translation is a content object 2. There is no canonical object - 3. The translation reference storage is external to the content - object + 3. The translation reference storage is external to the content object 4. Adapt all the steps on translation 5. Language get/set via an unified adapter 6. Translatable marker interface(s) @@ -323,35 +248,25 @@ The key points are: There is no canonical content object ------------------------------------ -Having a canonical object on the content space produces a dependency which is -not orthogonal with the normal behavior of Plone. Content objects should be -autonomous and you should be able to remove it. This is the reason because we -removed the canonical content object. There is a canonical object on the -translation infrastructure but is not on the content space. +Having a canonical object on the content space produces a dependency which is not orthogonal with the normal behavior of Plone. Content objects should be autonomous and you should be able to remove it. This is the reason because we removed the canonical content object. There is a canonical object on the translation infrastructure but is not on the content space. Translation reference storage ----------------------------- -In order to maintain the relations between the different language objects we -designed a common object called a *translation group*. This translation group -has an UUID on its own and each object member of the group stores it in the -object catalog register. You can use the ITranslationManager utility to access -and manipulate the members of a translation group given one object of the group. +In order to maintain the relations between the different language objects we designed a common object called a *translation group*. This translation group has an UUID on its own and each object member of the group stores it in the object catalog register. You can use the ITranslationManager utility to access and manipulate the members of a translation group given one object of the group. Adapt all the steps on translation ---------------------------------- -The different aspects involved on a translation are adapted, so it's possible -to create different policies for different types, sites, etc. +The different aspects involved on a translation are adapted, so it's possible to create different policies for different types, sites, etc. * ITranslationFactory - General factory used to create a new content * ITranslationLocator - Where we are going to locate the new translated content - Default : If the parent folder is translated create the content on the - translated parent folder, otherwise create on the parent folder. + Default : If the parent folder is translated create the content on the translated parent folder, otherwise create on the parent folder. * ITranslationCloner - Method to clone the original object to the new one @@ -369,8 +284,7 @@ to create different policies for different types, sites, etc. Language get/set via an unified adapter --------------------------------------- -In order to access and modify the language of a content type regardless the -type (Archetypes/Dexterity) there is a interface/adapter:: +In order to access and modify the language of a content type regardless the type (Archetypes/Dexterity) there is a interface/adapter:: Products.CMFPlone.interfaces.ILanguage @@ -391,6 +305,7 @@ In order to know if a content can be translated there is a marker interface:: plone.app.multilingual.interfaces.ITranslatable + Source Code =========== @@ -398,51 +313,8 @@ Contributors please read the document `Process for Plone core's development <htt Sources are at the `Plone code repository hosted at Github <https://github.com/plone/plone.app.multilingual>`_. + License ======= GNU General Public License, version 2 - - -Roadmap -======= - -This is the planned feature list for PAM: - -1.0 ---- - - * Babel view - * Root language folders - * Non invasive language selector - * Universal link - * Language selector policy - * Neutral root folder support - * Catalog based storage - * Translation map - * Google Translation Service integration - * LinguaPlone migration - - -2.0 (PLIP 13091) ----------------- - - * The first version compatible with PLIP 13091 - (https://dev.plone.org/ticket/13091) - * Update, get rid of legacy code and transfer some of the PAM logic to the - Plone core (plone.app.i18n) - * Perform the same for other parts of Plone core to integrate some monkey - patches and update legacy code from Products.PloneLanguageTool - - -3.0 ---- - - * XLIFF export/import - * Iterate support: we know there are some needs about iterate integration - * LinguaPlus/linguatools set of useful tools - * Outdated translations alerts and translation workflows support - * plone.app.toolbar/plone.app.cmsui support - * Add support for Deco layouts and content types - * Pluggable translation policies - * Pluggable language policies negotiations diff --git a/src/plone/app/multilingual/browser/menu.py b/src/plone/app/multilingual/browser/menu.py index dbc5be6..0874a4a 100644 --- a/src/plone/app/multilingual/browser/menu.py +++ b/src/plone/app/multilingual/browser/menu.py @@ -231,7 +231,7 @@ def getMenuItems(self, context, request): menu.append({ "title": _( u"shared_folder", - default=u"Go to Media folder" + default=u"Go to Assets folder" ), "description": _( u"description_shared_folder", diff --git a/src/plone/app/multilingual/browser/setup.py b/src/plone/app/multilingual/browser/setup.py index 3698b96..99e74b4 100644 --- a/src/plone/app/multilingual/browser/setup.py +++ b/src/plone/app/multilingual/browser/setup.py @@ -7,6 +7,7 @@ from plone.app.layout.navigation.interfaces import INavigationRoot from plone.app.multilingual.dx.interfaces import IDexterityTranslatable from Products.CMFPlone.interfaces import ILanguage +from plone.app.multilingual import _ from plone.app.multilingual.interfaces import ITranslatable from plone.app.multilingual.interfaces import ITranslationManager from plone.app.multilingual.interfaces import LANGUAGE_INDEPENDENT @@ -16,6 +17,7 @@ from plone.i18n.locales.languages import _languagelist from zope.component.hooks import getSite from zope.event import notify +from zope.i18n import translate from zope.interface import alsoProvides from zope.lifecycleevent import modified @@ -38,7 +40,7 @@ class SetupMultilingualSite(object): # portal_type that is added as root language folder folder_type = 'LRF' - # portal_type that is added as language independent media folder + # portal_type that is added as language independent asset folder folder_type_language_independent = 'LIF' def __init__(self, context=None): @@ -134,18 +136,25 @@ def setUpLanguage(self, code, name): folder = getattr(self.context, folderId, None) wftool = getToolByName(self.context, 'portal_workflow') + assets_folder_id = translate(_('assets_folder_id', + default='assets'), + target_language=folderId) + assets_folder_title = translate(_('assets_folder_title', + default=u'Assets'), + target_language=folderId) + if folder is None: _createObjectByType(self.folder_type, self.context, folderId) _createObjectByType(self.folder_type_language_independent, - self.context[folderId], 'media') + self.context[folderId], assets_folder_id) folder = self.context[folderId] ILanguage(folder).set_language(code) folder.setTitle(name) - ILanguage(folder['media']).set_language(code) - folder['media'].setTitle(u'Media') + ILanguage(folder[assets_folder_id]).set_language(code) + folder[assets_folder_id].setTitle(assets_folder_title) # This assumes a direct 'publish' transition from the initial state # We are going to check if its private and has publish action for @@ -156,24 +165,25 @@ def setUpLanguage(self, code, name): if state != 'published' and 'publish' in available_transitions: wftool.doActionFor(folder, 'publish') - state = wftool.getInfoFor(folder['media'], 'review_state', None) + state = wftool.getInfoFor(folder[assets_folder_id], + 'review_state', None) available_transitions = [t['id'] for t in - wftool.getTransitionsFor(folder['media'])] + wftool.getTransitionsFor(folder[assets_folder_id])] # noqa if state != 'published' and 'publish' in available_transitions: - wftool.doActionFor(folder['media'], 'publish') + wftool.doActionFor(folder[assets_folder_id], 'publish') # Exclude folder from navigation (if applicable) adapter = IExcludeFromNavigation(folder, None) if adapter is not None: adapter.exclude_from_nav = True - adapter = IExcludeFromNavigation(folder['media'], None) + adapter = IExcludeFromNavigation(folder[assets_folder_id], None) if adapter is not None: adapter.exclude_from_nav = True # We've modified the object; reindex. notify(modified(folder)) - notify(modified(folder['media'])) + notify(modified(folder[assets_folder_id])) doneSomething = True logger.info(u"Added '%s' folder: %s" % (code, folderId)) diff --git a/src/plone/app/multilingual/tests/test_catalog.py b/src/plone/app/multilingual/tests/test_catalog.py index f50b9cb..7eb11af 100644 --- a/src/plone/app/multilingual/tests/test_catalog.py +++ b/src/plone/app/multilingual/tests/test_catalog.py @@ -16,7 +16,7 @@ def setUp(self): self.request = self.layer['request'] alsoProvides(self.layer['request'], IPloneAppMultilingualInstalled) createContentInContainer( - self.portal['en']['media'], 'Document', title=u"Test document") + self.portal['en']['assets'], 'Document', title=u"Test document") # ^ This will be shadowed to all language independent folders createContentInContainer( diff --git a/src/plone/app/multilingual/tests/test_lrf.py b/src/plone/app/multilingual/tests/test_lrf.py index 8d22bbd..af58962 100644 --- a/src/plone/app/multilingual/tests/test_lrf.py +++ b/src/plone/app/multilingual/tests/test_lrf.py @@ -24,34 +24,34 @@ def setUp(self): def test_shared_content(self): # Create shared document createContentInContainer( - self.portal.en.media, 'Document', title=u"Test document") + self.portal.en.assets, 'Document', title=u"Test document") # Check shared document is there - self.assertEqual(self.portal.en.media['test-document'], - self.portal.ca.media['test-document']) - self.assertEqual(self.portal.en.media['test-document'], - self.portal.es.media['test-document']) + self.assertEqual(self.portal.en.assets['test-document'], + self.portal.ca.assets['test-document']) + self.assertEqual(self.portal.en.assets['test-document'], + self.portal.es.assets['test-document']) # Delete shared document - notify(ObjectWillBeRemovedEvent(self.portal.en.media['test-document'])) - self.portal.en.media.manage_delObjects('test-document') + notify(ObjectWillBeRemovedEvent(self.portal.en.assets['test-document'])) + self.portal.en.assets.manage_delObjects('test-document') # Check that it is not available in LRFs - self.assertNotIn('test-document', self.portal.ca.media.objectIds()) - self.assertNotIn('test-document', self.portal.es.media.objectIds()) + self.assertNotIn('test-document', self.portal.ca.assets.objectIds()) + self.assertNotIn('test-document', self.portal.es.assets.objectIds()) def test_shared_content_indexing(self): # Create shared document createContentInContainer( - self.portal.en.media, 'Document', title=u"Test document") + self.portal.en.assets, 'Document', title=u"Test document") # Check that shared document is indexed in all LRFs elements = self.portal.portal_catalog.searchResults(id='test-document') self.assertEqual(len(elements), 3) # Remove shared document - notify(ObjectWillBeRemovedEvent(self.portal.en.media['test-document'])) - self.portal.en.media.manage_delObjects('test-document') + notify(ObjectWillBeRemovedEvent(self.portal.en.assets['test-document'])) + self.portal.en.assets.manage_delObjects('test-document') # Check that shared document is unindexed elements = self.portal.portal_catalog.searchResults(id='test-document') @@ -60,45 +60,45 @@ def test_shared_content_indexing(self): def test_shared_content_uuid(self): # Create shared document createContentInContainer( - self.portal, 'LIF', title=u"Media", checkConstraints=False) + self.portal, 'LIF', title=u"Assets", checkConstraints=False) createContentInContainer( - self.portal.media, 'Document', title=u"Test document") + self.portal.assets, 'Document', title=u"Test document") - root_uuid = IUUID(self.portal.media['test-document']) - shared_uuid = IUUID(self.portal.ca.media['test-document']) + root_uuid = IUUID(self.portal.assets['test-document']) + shared_uuid = IUUID(self.portal.ca.assets['test-document']) self.assertEqual('{0:s}-ca'.format(root_uuid), shared_uuid) def test_moving_shared_content_to_lrf(self): # Create shared document createContentInContainer( - self.portal, 'LIF', title=u"Media", checkConstraints=False) + self.portal, 'LIF', title=u"Assets", checkConstraints=False) createContentInContainer( - self.portal.media, 'Document', title=u"Test document") - uuid = IUUID(self.portal.media['test-document']) + self.portal.assets, 'Document', title=u"Test document") + uuid = IUUID(self.portal.assets['test-document']) # Check that ghost is ghost self.assertTrue( - is_language_independent(self.portal.ca.media['test-document'])) + is_language_independent(self.portal.ca.assets['test-document'])) # Check is in the catalog brains = self.portal.portal_catalog.searchResults(UID=uuid) self.assertEqual(len(brains), 1) - self.assertEqual(brains[0].getPath(), '/plone/media/test-document') + self.assertEqual(brains[0].getPath(), '/plone/assets/test-document') brains = self.portal.portal_catalog.searchResults( UID='{0:s}-ca'.format(uuid)) self.assertEqual(len(brains), 1) - self.assertEqual(brains[0].getPath(), '/plone/ca/media/test-document') + self.assertEqual(brains[0].getPath(), '/plone/ca/assets/test-document') brains = self.portal.portal_catalog.searchResults( UID='{0:s}-es'.format(uuid)) self.assertEqual(len(brains), 1) - self.assertEqual(brains[0].getPath(), '/plone/es/media/test-document') + self.assertEqual(brains[0].getPath(), '/plone/es/assets/test-document') # MOVE! moved = multilingualMoveObject( - self.portal.ca.media['test-document'], 'ca') + self.portal.ca.assets['test-document'], 'ca') # Check that the old and the new uuid are the same moved_uuid = IUUID(self.portal.ca['test-document']) diff --git a/src/plone/app/multilingual/tests/test_sitemap.py b/src/plone/app/multilingual/tests/test_sitemap.py index f46a2d7..e995617 100644 --- a/src/plone/app/multilingual/tests/test_sitemap.py +++ b/src/plone/app/multilingual/tests/test_sitemap.py @@ -30,7 +30,7 @@ def setUp(self): name='sitemap.xml.gz') createContentInContainer( - self.portal['en']['media'], 'Document', title=u"Test document") + self.portal['en']['assets'], 'Document', title=u"Test document") # ^ This will be shadowed to all language independent folders createContentInContainer( @@ -59,9 +59,9 @@ def test_portalroot_sitemap(self): self.assertIn('<loc>http://nohost/plone/en/test-document</loc>', xml) self.assertIn('<loc>http://nohost/plone/es/test-document</loc>', xml) - self.assertIn('<loc>http://nohost/plone/ca/media/test-document</loc>', xml) # noqa - self.assertIn('<loc>http://nohost/plone/en/media/test-document</loc>', xml) # noqa - self.assertIn('<loc>http://nohost/plone/es/media/test-document</loc>', xml) # noqa + self.assertIn('<loc>http://nohost/plone/ca/assets/test-document</loc>', xml) + self.assertIn('<loc>http://nohost/plone/en/assets/test-document</loc>', xml) + self.assertIn('<loc>http://nohost/plone/es/assets/test-document</loc>', xml) def test_navroot_sitemap(self): ''' @@ -74,6 +74,6 @@ def test_navroot_sitemap(self): self.assertNotIn('<loc>http://nohost/plone/en/test-document</loc>', xml) # noqa self.assertIn('<loc>http://nohost/plone/es/test-document</loc>', xml) - self.assertNotIn('<loc>http://nohost/plone/ca/media/test-document</loc>', xml) # noqa - self.assertNotIn('<loc>http://nohost/plone/en/media/test-document</loc>', xml) # noqa - self.assertIn('<loc>http://nohost/plone/es/media/test-document</loc>', xml) # noqa + self.assertNotIn('<loc>http://nohost/plone/ca/assets/test-document</loc>', xml) + self.assertNotIn('<loc>http://nohost/plone/en/assets/test-document</loc>', xml) + self.assertIn('<loc>http://nohost/plone/es/assets/test-document</loc>', xml) diff --git a/src/plone/app/multilingual/tests/test_subscribers.py b/src/plone/app/multilingual/tests/test_subscribers.py index 3a78465..70c41ee 100644 --- a/src/plone/app/multilingual/tests/test_subscribers.py +++ b/src/plone/app/multilingual/tests/test_subscribers.py @@ -65,87 +65,87 @@ def test_copied_event(self): a_ca_copied = self.portal['en'][a_ca.id] self.assertEqual(ILanguage(a_ca_copied).get_language(), 'en') - def test_moved_to_media_folder(self): + def test_moved_to_assets_folder(self): """When an object is moved from within one Language Root Folder into - the Language Independent Folder (named 'Media') it becomes language - independent, and it should be visible from the media folder accessed + the Language Independent Folder (named 'Assets') it becomes language + independent, and it should be visible from the assets folder accessed from within other Language Root Folders """ a_ca = createContentInContainer( self.portal['ca'], 'Document', title=u"Test document") # Test a paste into a subfolder to be ultra cautious - ca_media_subfolder = createContentInContainer( - self.portal['ca']['media'], 'Folder', title=u"A Folder") + ca_assets_subfolder = createContentInContainer( + self.portal['ca']['assets'], 'Folder', title=u"A Folder") - subfolder_name = ca_media_subfolder.id + subfolder_name = ca_assets_subfolder.id id_ = self.portal['ca'].manage_cutObjects(a_ca.id) - ca_media_subfolder.manage_pasteObjects(id_) + ca_assets_subfolder.manage_pasteObjects(id_) - # Get both media folders afresh - ca_media_subfolder = self.portal['ca']['media'][subfolder_name] - en_media_subfolder = self.portal['en']['media'][subfolder_name] + # Get both assets folders afresh + ca_assets_subfolder = self.portal['ca']['assets'][subfolder_name] + en_assets_subfolder = self.portal['en']['assets'][subfolder_name] # Check it is in both folder listings - self.assertTrue(a_ca.id in ca_media_subfolder) - self.assertTrue(a_ca.id in en_media_subfolder) + self.assertTrue(a_ca.id in ca_assets_subfolder) + self.assertTrue(a_ca.id in en_assets_subfolder) # Check it is language independent - copy_in_en = en_media_subfolder[a_ca.id] + copy_in_en = en_assets_subfolder[a_ca.id] self.assertEqual(ILanguage(copy_in_en).get_language(), '') - copy_in_ca = ca_media_subfolder[a_ca.id] + copy_in_ca = ca_assets_subfolder[a_ca.id] self.assertEqual(ILanguage(copy_in_ca).get_language(), '') # Check it is returned in catalog search catalog = getToolByName(self.portal, 'portal_catalog') - ca_subfolder_path = '/'.join(ca_media_subfolder.getPhysicalPath()) + ca_subfolder_path = '/'.join(ca_assets_subfolder.getPhysicalPath()) ca_folder_contents = [r.id for r in catalog(path=ca_subfolder_path)] self.assertTrue(a_ca.id in ca_folder_contents) - en_subfolder_path = '/'.join(en_media_subfolder.getPhysicalPath()) + en_subfolder_path = '/'.join(en_assets_subfolder.getPhysicalPath()) en_folder_contents = [r.id for r in catalog(path=en_subfolder_path)] self.assertTrue(a_ca.id in en_folder_contents) - def test_copied_to_media_folder(self): + def test_copied_to_assets_folder(self): """When an object is copied from within one Language Root Folder into - the Language Independent Folder (named 'Media') it becomes language - independent, and it should be visible from the media folder accessed + the Language Independent Folder (named 'Assets') it becomes language + independent, and it should be visible from the assets folder accessed from within other Language Root Folders """ a_ca = createContentInContainer( self.portal['ca'], 'Document', title=u"Test document") # Test a paste into a subfolder to be ultra cautious - ca_media_subfolder = createContentInContainer( - self.portal['ca']['media'], 'Folder', title=u"A Folder") + ca_assets_subfolder = createContentInContainer( + self.portal['ca']['assets'], 'Folder', title=u"A Folder") - subfolder_name = ca_media_subfolder.id + subfolder_name = ca_assets_subfolder.id id_ = self.portal['ca'].manage_copyObjects(a_ca.id) - ca_media_subfolder.manage_pasteObjects(id_) + ca_assets_subfolder.manage_pasteObjects(id_) - # Get both media folders afresh - ca_media_subfolder = self.portal['ca']['media'][subfolder_name] - en_media_subfolder = self.portal['en']['media'][subfolder_name] + # Get both assets folders afresh + ca_assets_subfolder = self.portal['ca']['assets'][subfolder_name] + en_assets_subfolder = self.portal['en']['assets'][subfolder_name] # Check it is in both folder listings - self.assertTrue(a_ca.id in ca_media_subfolder) - self.assertTrue(a_ca.id in en_media_subfolder) + self.assertTrue(a_ca.id in ca_assets_subfolder) + self.assertTrue(a_ca.id in en_assets_subfolder) # Check it is language independent - copy_in_en = en_media_subfolder[a_ca.id] + copy_in_en = en_assets_subfolder[a_ca.id] self.assertEqual(ILanguage(copy_in_en).get_language(), '') - copy_in_ca = ca_media_subfolder[a_ca.id] + copy_in_ca = ca_assets_subfolder[a_ca.id] self.assertEqual(ILanguage(copy_in_ca).get_language(), '') # Check it is returned in catalog search catalog = getToolByName(self.portal, 'portal_catalog') - ca_subfolder_path = '/'.join(ca_media_subfolder.getPhysicalPath()) + ca_subfolder_path = '/'.join(ca_assets_subfolder.getPhysicalPath()) ca_folder_contents = [r.id for r in catalog(path=ca_subfolder_path)] self.assertTrue(a_ca.id in ca_folder_contents) - en_subfolder_path = '/'.join(en_media_subfolder.getPhysicalPath()) + en_subfolder_path = '/'.join(en_assets_subfolder.getPhysicalPath()) en_folder_contents = [r.id for r in catalog(path=en_subfolder_path)] self.assertTrue(a_ca.id in en_folder_contents) ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot