Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error on translate pages #1461

Closed
gabpaladino opened this issue Mar 15, 2012 · 46 comments
Closed

error on translate pages #1461

gabpaladino opened this issue Mar 15, 2012 · 46 comments

Comments

@gabpaladino
Copy link

i have some problems on translate pages on version 2.0.1 with ruby 1.9.3

basically errors caused by wrong urls. i fix change the admin templates (page and form) to use page.id and not uncached_nested_url on links and form action.

error occours on...

About
| - The Company
| - Clients
.............

So i translate About page, then i will translate The Company, but the url like "about/5" generate a page nil object on form.

I changed on page partial and ok, so again on form action i have a put action "about/5" thats generate a undefined method 'update_attributes' for nil class.. so again i edit form partial and change action to use only page.id

@parndt
Copy link
Member

parndt commented Mar 17, 2012

So you've modified the code and it's not working for you?

Can you provide a default application (without modification) that fails?

@gabpaladino
Copy link
Author

Hi, with modification works fine.

The urls (on admin) are now only with page id, not slugs, and working fine..

I can try to reproduce error on sqlite db and send to you because my application is in production..

@kalabiyau
Copy link

From fresh install i get the same

gem install refinerycms
refinerycms reftest
cd reftest
change locale to ru 
Refinery::I18n.configure do |config|
  config.current_locale = :ru
  config.default_locale = :ru
  config.default_frontend_locale = :ru
  config.enabled = true
  config.frontend_locales = [:ru, :en]
  config.locales = { :en => 'English', :ru => 'Русский' }
end
rails s ...

add some page in :ru locale - ok
tryiung to edit same page but on en locale
http://localhost:3000/refinery/pages/home/asdas/edit?switch_locale=en
cahnge titlte -> save
return this url http://localhost:3000/refinery/pages/home/4
and stack
eval):59:in `update'
actionpack (3.2.2) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
actionpack (3.2.2) lib/abstract_controller/base.rb:167:in `process_action'
actionpack (3.2.2) lib/action_controller/metal/rendering.rb:10:in `process_action'
actionpack (3.2.2) lib/abstract_controller/callbacks.rb:18:in `block in process_action'
activesupport (3.2.2) lib/active_support/callbacks.rb:503:in `block in _run__857878755612405008__process_action__913487748095132968__callbacks'
activesupport (3.2.2) lib/active_support/callbacks.rb:215:in `block in _conditional_callback_around_373'
activesupport (3.2.2) lib/active_support/callbacks.rb:326:in `around'
activesupport (3.2.2) lib/active_support/callbacks.rb:310:in `_callback_around_345'
activesupport (3.2.2) lib/active_support/callbacks.rb:214:in `_conditional_callback_around_373'
activesupport (3.2.2) lib/active_support/callbacks.rb:491:in `_run__857878755612405008__process_action__913487748095132968__callbacks'
activesupport (3.2.2) lib/active_support/callbacks.rb:405:in `__run_callback'
activesupport (3.2.2) lib/active_support/callbacks.rb:385:in `_run_process_action_callbacks'
activesupport (3.2.2) lib/active_support/callbacks.rb:81:in `run_callbacks'
actionpack (3.2.2) lib/abstract_controller/callbacks.rb:17:in `process_action'
actionpack (3.2.2) lib/action_controller/metal/rescue.rb:29:in `process_action'
actionpack (3.2.2) lib/action_controller/metal/instrumentation.rb:30:in `block in process_action'
activesupport (3.2.2) lib/active_support/notifications.rb:123:in `block in instrument'
activesupport (3.2.2) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
activesupport (3.2.2) lib/active_support/notifications.rb:123:in `instrument'
actionpack (3.2.2) lib/action_controller/metal/instrumentation.rb:29:in `process_action'
actionpack (3.2.2) lib/action_controller/metal/params_wrapper.rb:205:in `process_action'
activerecord (3.2.2) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
actionpack (3.2.2) lib/abstract_controller/base.rb:121:in `process'
actionpack (3.2.2) lib/abstract_controller/rendering.rb:45:in `process'
actionpack (3.2.2) lib/action_controller/metal.rb:203:in `dispatch'
actionpack (3.2.2) lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'
actionpack (3.2.2) lib/action_controller/metal.rb:246:in `block in action'
actionpack (3.2.2) lib/action_dispatch/routing/route_set.rb:67:in `call'
actionpack (3.2.2) lib/action_dispatch/routing/route_set.rb:67:in `dispatch'
actionpack (3.2.2) lib/action_dispatch/routing/route_set.rb:30:in `call'
journey (1.0.3) lib/journey/router.rb:68:in `block in call'
journey (1.0.3) lib/journey/router.rb:56:in `each'
journey (1.0.3) lib/journey/router.rb:56:in `call'
actionpack (3.2.2) lib/action_dispatch/routing/route_set.rb:594:in `call'
railties (3.2.2) lib/rails/engine.rb:479:in `call'
railties (3.2.2) lib/rails/railtie/configurable.rb:30:in `method_missing'
journey (1.0.3) lib/journey/router.rb:68:in `block in call'
journey (1.0.3) lib/journey/router.rb:56:in `each'
journey (1.0.3) lib/journey/router.rb:56:in `call'
actionpack (3.2.2) lib/action_dispatch/routing/route_set.rb:594:in `call'
warden (1.1.1) lib/warden/manager.rb:35:in `block in call'
warden (1.1.1) lib/warden/manager.rb:34:in `catch'
warden (1.1.1) lib/warden/manager.rb:34:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
rack (1.4.1) lib/rack/etag.rb:23:in `call'
rack (1.4.1) lib/rack/conditionalget.rb:35:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/head.rb:14:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/params_parser.rb:21:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/flash.rb:242:in `call'
rack (1.4.1) lib/rack/session/abstract/id.rb:205:in `context'
rack (1.4.1) lib/rack/session/abstract/id.rb:200:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/cookies.rb:338:in `call'
dragonfly (0.9.11) lib/dragonfly/cookie_monster.rb:9:in `call'
activerecord (3.2.2) lib/active_record/query_cache.rb:64:in `call'
activerecord (3.2.2) lib/active_record/connection_adapters/abstract/connection_pool.rb:443:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (3.2.2) lib/active_support/callbacks.rb:405:in `_run__3188154975727205554__call__1846873864934704366__callbacks'
activesupport (3.2.2) lib/active_support/callbacks.rb:405:in `__run_callback'
activesupport (3.2.2) lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
activesupport (3.2.2) lib/active_support/callbacks.rb:81:in `run_callbacks'
actionpack (3.2.2) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
dragonfly (0.9.11) lib/dragonfly/middleware.rb:13:in `call'
dragonfly (0.9.11) lib/dragonfly/middleware.rb:13:in `call'
rack-cache (1.2) lib/rack/cache/context.rb:136:in `forward'
rack-cache (1.2) lib/rack/cache/context.rb:143:in `pass'
rack-cache (1.2) lib/rack/cache/context.rb:155:in `invalidate'
rack-cache (1.2) lib/rack/cache/context.rb:71:in `call!'
rack-cache (1.2) lib/rack/cache/context.rb:51:in `call'
rack-cache (1.2) lib/rack/cache/context.rb:136:in `forward'
rack-cache (1.2) lib/rack/cache/context.rb:143:in `pass'
rack-cache (1.2) lib/rack/cache/context.rb:155:in `invalidate'
rack-cache (1.2) lib/rack/cache/context.rb:71:in `call!'
rack-cache (1.2) lib/rack/cache/context.rb:51:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/reloader.rb:65:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/remote_ip.rb:31:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
railties (3.2.2) lib/rails/rack/logger.rb:26:in `call_app'
railties (3.2.2) lib/rails/rack/logger.rb:16:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/request_id.rb:22:in `call'
rack (1.4.1) lib/rack/methodoverride.rb:21:in `call'
rack (1.4.1) lib/rack/runtime.rb:17:in `call'
activesupport (3.2.2) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
rack (1.4.1) lib/rack/lock.rb:15:in `call'
actionpack (3.2.2) lib/action_dispatch/middleware/static.rb:61:in `call'
railties (3.2.2) lib/rails/engine.rb:479:in `call'
railties (3.2.2) lib/rails/application.rb:220:in `call'
rack (1.4.1) lib/rack/content_length.rb:14:in `call'
railties (3.2.2) lib/rails/rack/log_tailer.rb:14:in `call'
rack (1.4.1) lib/rack/handler/webrick.rb:59:in `service'
/home/achernikov/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/webrick/httpserver.rb:138:in `service'
/home/achernikov/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/webrick/httpserver.rb:94:in `run'
/home/achernikov/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'
Request

Parameters:

{"utf8"=>"✓",
 "_method"=>"put",
 "authenticity_token"=>"dfvzwWHhnXvWXReERRxr6VPLoytmI0kNJAymMGe8PiE=",
 "switch_locale"=>"en",
 "page"=>{"title"=>"asdasd",
 "parts_attributes"=>{"0"=>{"body"=>"",
 "position"=>"0",
 "id"=>"6"},
 "1"=>{"body"=>"",
 "position"=>"1",
 "id"=>"7"}},
 "draft"=>"0",
 "parent_id"=>"1",
 "menu_title"=>"",
 "skip_to_first_child"=>"0",
 "link_url"=>"",
 "show_in_menu"=>"1",
 "browser_title"=>"",
 "meta_keywords"=>"",
 "meta_description"=>""},
 "continue_editing"=>"false",
 "path"=>"home/4",
 "locale"=>:ru}

NoMethodError in Refinery::Admin::PagesController#update

undefined method `update_attributes' for nil:NilClass

@kalabiyau
Copy link

Maybe page translation resource was not builded before update_attribute ?

@kalabiyau
Copy link

I think this is related

Showing /home/achernikov/.rvm/gems/ruby-1.9.3-p125/gems/refinerycms-pages-2.0.2/app/views/refinery/admin/pages/_form.html.erb where line #2 raised:

undefined method `persisted?' for nil:NilClass

@kalabiyau
Copy link

Checked another time. All the same. Problem can be reproduced only on nested pages with translation

@gabpaladino
Copy link
Author

@parndt the problem reported by @kalabiyau it's exactly like my....

so, the changes that i made..

on https://github.com/resolve/refinerycms/blob/master/pages/app/views/refinery/admin/pages/_page.html.erb

line 16 to refinery.edit_admin_page_path(page.id, :switch_locale => translation.locale),
line 34 to refinery.edit_admin_page_path(page.id),
line 38 to refinery.admin_page_path(page.id),

and file https://github.com/resolve/refinerycms/blob/master/pages/app/views/refinery/admin/pages/_form.html.erb

line 2 to :url => (refinery.admin_page_path(@page.id) if @page.persisted?) do |f| %>

so i think that can be used only page ids on admin, slugs are not necessary..

@bettysteger
Copy link

but it is not in the master yet?

@gabpaladino
Copy link
Author

i not pushed to repo, i dont know if is the best option... solve to me and posted to exterts evaluate :)

@bettysteger
Copy link

do you get that file with the override rake task? this doesn't work:

bundle exec rake refinery:override view=refinery/admin/pages/page

@gabpaladino
Copy link
Author

i get directly from github...

but you can use

bundle exec rake refinery:override view=refinery/admin/pages/_page :)

@bettysteger
Copy link

thanks!

@patizivs
Copy link

Thank you for solution!

@ebeigarts
Copy link

@gabpaladino thanks!

@renegr
Copy link

renegr commented Apr 20, 2012

Here is some brainfood (thanks to @phiggins, who brought up some interesting points on this topic)

Solutions for the backend:

@phiggins input related to this:

  • When you use a URL helper in Rails like refinery.admin_page_path(@page), for example, it will call the Refinery::Page#to_param on @page and it currently is not very intelligent in terms of i18n (as you've seen) and things like nested pages (try creating a page with the title "foo", and then another page with the title "foo" that has the first one as its parent, and then call #to_param on both of them).

The following part covers three solutions and their explanations I've been going through. See it as a starting point for a discussion on a proper solution.

  1. Fallback to any existing translation on each page:

    Use the first(?!) alternative slug translation that is available for this page.

    Three examples that show the rather odd behaviour:

    a.) If you have an English Parent named "About" and a child named "Mitarbeiter", the backend url would read about/mitarbeiter

    b.) If you have an german (only!) parent named "Über uns" and a child named "Team", the backend url would read uber-uns/team

    c.) If you have several languages set up (but not english), the mixin could get rather nasty - Who decides what locale shall be considered??

  2. Try to resolve the complete path in one existing language:

    If there is an english page named "About" and it's translation "Über uns",
    and a child page named "Mitarbeiter" (german only), which has a child page "Peter Parker(de)" (german and english)
    Then the complete path should resolve as uber-uns/mitarbeiter/peter-parkerde, when editing the english version of "Peter Parker"

    Three thoughts, why I would not consider this as a proper solution:

    a.) You would have to check for every nested path the optimal path, which lacks performance

    b.) It's ackward for the user, seeing the full (in this example) german path, when editing the english version

    c.) There might be some cases where a fallback to one language is impossible

  3. Just use the ID:

    Due to these many reasons, I can only think of two solutions: First: Just use the plain simple ID of the current page.
    This seems to me a consistent solution for such a big variaty of different (kind of unpredictable in it's amount) use cases..

  4. Let Page.find_by_path resolve mixed slugs like /5/some-page/6

    This is another possible solution, which would probably perform (in terms of performance) as good, as the current version (which actually fails on such pathes at the moment)

Solution for the frontend:

@phiggins input:

  • The other side of this, when doing page lookup based on the request path, there are also gaps in functionality there. If I have a page with the english slug "home" and the spanish slug "mi-casa" and I visit "/es/home", what should happen?

My humble oppinion is as follows:

  • Visiting /es/home should fail (404 not found), since each language should be considered seperate for the outside (just consider SEO)
  • The only valid nested_path should be the one that covers every page(slug) in the chosen language.

@gabpaladino
Copy link
Author

Hi @renegr, i think that option 3 it's convenient for backend, we dosen't need seo in backend and it's more simple!

I not tested the frontend question but my opnion is to make a 301 redirect to the "/es/mi-casa" or "en/home", but i have no ideia if the language or page has preference... hehehehe. so the 404 error can be a good solution too.

@parndt
Copy link
Member

parndt commented Apr 22, 2012

My 2c: Ideally the backend and frontend should be using identical routing so that a problem on the frontend is also a problem on the backend which would help us to make routing work perfectly in both situations. Edge cases / differences make programming harder :-)

@renegr
Copy link

renegr commented Apr 22, 2012

Hi,

@parndt I agree: I think that it would be a nice solution from the programmers view. But this would mean that the only proper solution is number 1 (if we want to retain the pretty-url feature :-)) so far. Which - in my opinion - is kind of ugly from the users view (backend as well as frontend)...

What I tried to outline in the examples above, is that the use-cases of paths are of so much more variety in the backend as in the frontend. The problems that have to be faced in the backend are not to be faced in the frontend, which makes it kind of different problems to me (in detail, see above: big differences in terms of complexity)

Number 4 seems to me not a valuable solution anymore, because it would make it hard to resolve paths which are named e.g. "4" and has an ID of "20". When the paths reads /about/4, you would have to check for a page named 4 (first) and then for the ID. What if you get two results? No go - in my opinion.

At the moment I can not think of a nice solution that solves both fields (backend and frontend), without confusing user and without confusing programmer, since - once again - the backend faces so much more problems, then the frontend should ever face ...

Thanks for your thoughts! Looking forward for a leap on this topic!
What do you think?

@parndt
Copy link
Member

parndt commented Jun 8, 2012

We've made a lot of changes recently to functionality around this. Is the current [master/2-0-stable] functionality still buggy?

@gabpaladino
Copy link
Author

Hi @parndt i will test the lastest changes and return with news.

@cantonic
Copy link

i tried using 2-0-stable and it's still buggy

@groe
Copy link

groe commented Aug 21, 2012

I am currently experiencing the same problem, running refinerycms-core-2.0.5.

Any news on this?

@groe
Copy link

groe commented Aug 21, 2012

I just noticed that 2.0.8 is out already. Just upgraded; seems like that problem still exists.

@tailic
Copy link

tailic commented Sep 1, 2012

Same here with 2.0.8, I used gabpaladinos changes to fix this for now.

@rickyah
Copy link
Contributor

rickyah commented Sep 2, 2012

I confirm that version 2.0.8 still has this bug, and needed to use gabpaladino's fix

@pavelnikolov
Copy link

Thank you soo much for this fix. I saved me a lot of time.
I am building a website with bulgarian and czech content. I was able to create bulgarian pages but when I tried to create czech translation I had the same problem. I think you have to make a pull request and merge this into the master branch. I'm using 2.0.8.

@ugisozols
Copy link
Member

@pavelnikolov which comment are you referring to?

@pavelnikolov
Copy link

@ugisozols,

I used the override rake task like this:

bundle exec rake refinery:override view=refinery/admin/pages/_page
bundle exec rake refinery:override view=refinery/admin/pages/_form

and then applied the changes suggested by @gabpaladino
in this comment

so now everything works like a charm

@robyurkowski
Copy link
Contributor

@parndt When do we want to deal with this one? Should we try to slam it in for 2.1 or should this be pushed to 3.0?

@parndt
Copy link
Member

parndt commented Nov 10, 2012

2.1 or 2.2 if possible

@parndt
Copy link
Member

parndt commented Dec 18, 2012

Investigating..

@parndt
Copy link
Member

parndt commented Dec 20, 2012

Fixed by #2088

@parndt parndt closed this as completed Dec 20, 2012
parndt added a commit that referenced this issue Dec 20, 2012
parndt added a commit that referenced this issue Dec 20, 2012
Updated to globalize3 version 0.3.0

Fixes #1461

Conflicts:
	Gemfile
	core/refinerycms-core.gemspec
	pages/app/controllers/refinery/admin/pages_controller.rb
	pages/app/models/refinery/page.rb
	pages/app/views/refinery/admin/pages/_form.html.erb
	pages/app/views/refinery/admin/pages/_locale_picker.html.erb
	pages/app/views/refinery/admin/pages/_page.html.erb
@harley
Copy link

harley commented Jan 8, 2013

i still get the error with the latest code from 2-0-stable branch (verified that the bundled refinerycms version includes the above changes). steps to reproduce:

  1. default locale and front end is not English (e.g. vi)
  2. add a child page then save (must be a child page -- no problem with the parent page)
  3. click to edit that page, then switch locale to English
  4. save the page -- the same exception described in this issue still occurs

i no longer have to override the _page partial but still have to change @page.nested_url (or previously @page.uncached_nested_url, which is the same thing) in the latest code to @page.id in _form partial for it to work.

the difference it makes is that in my case @page.nested_url gives refinery/pages/about/51 while @page.id gives refinery/pages/51. the former causes the page to crash because it won't find @page in the update action. from the log

Refinery::Page Load (0.8ms) SELECT "refinery_pages".* FROM "refinery_pages" INNER JOIN "refinery_page_translations" ON "refinery_page_translations"."refinery_page_id" = "refinery_pages"."id" WHERE "refinery_page_translations"."locale" IN ('en', 'vi') AND "refinery_page_translations"."slug" = 'about' AND "refinery_pages"."parent_id" IS NULL LIMIT 1

somehow parent_id is NULL above when it shouldn't be? here's the request (the word parent_id in bold)

Started PUT "/refinery/pages/about/51" for 127.0.0.1 at 2013-01-08 16:03:26 +0700
Processing by Refinery::Admin::PagesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ZEn185xaWO7l4sR8oAhvRxz/7aqikGuaGmQM2ZqDOwQ=", "switch_locale"=>"en", "page"=>{"title"=>"test E2", "parts_attributes"=>{"0"=>{"body"=>"", "position"=>"0", "id"=>"98"}, "1"=>{"body"=>"", "position"=>"1", "id"=>"99"}}, "images_attributes"=>{"0"=>{"id"=>""}}, "draft"=>"0", "parent_id"=>"16", "menu_title"=>"", "skip_to_first_child"=>"0", "link_url"=>"", "show_in_menu"=>"1", "browser_title"=>"", "meta_keywords"=>"", "meta_description"=>""}, "continue_editing"=>"false", "path"=>"about/51", "locale"=>:vi}

thanks

@parndt
Copy link
Member

parndt commented Jan 8, 2013

This was fixed in master not 2-0-stable

@harley
Copy link

harley commented Jan 8, 2013

@parndt i verified that your pull/commit was applied to 2-0-stable as well

@simi
Copy link
Member

simi commented Jan 8, 2013

@harleyttd: Doubting Thomas :)

@harley
Copy link

harley commented Jan 8, 2013

@simi :) thanks i'll be better next time

https://github.com/refinery/refinerycms/commits/2-0-stable shows that @parndt's pull #2088 was merged on Dec 20, 2012

i did mention that i also verified that my bundled version of refinerycms is up to date with the latest commit in that branch

sorry if i miss anything obvious

@parndt
Copy link
Member

parndt commented Jan 8, 2013

Oh sorry, I guess I did write this for 2-0-stable in the first place.. I'll see if I can reproduce your case.

@parndt
Copy link
Member

parndt commented Jan 8, 2013

Confirm the issue still exists 😢

@parndt parndt reopened this Jan 8, 2013
@parndt parndt closed this as completed in e3e6263 Jan 8, 2013
@parndt
Copy link
Member

parndt commented Jan 8, 2013

@harleyttd please try updating to the latest 2-0-stable, this works now for me 👍

@harley
Copy link

harley commented Jan 11, 2013

ah hah nice fix! confirmed this works for me too. thanks so much!

gwagener pushed a commit to gwagener/refinerycms that referenced this issue Jan 14, 2013
@jurriaan
Copy link
Contributor

The bug still exists for me in refinery 2.0.10..

I'm importing a existing page structure from another CMS which has a deeply nested page structure.
I've got three levels of translated pages which contain a non-translated page.

The admin generates urls like this: /refinery/pages/branches/bakery/bread/2907/edit?switch_locale=nl
which doesn't work. If I change the url to /refinery/pages/2907/edit?switch_locale=nl it does work and I can edit the page.

@parndt
Copy link
Member

parndt commented Apr 17, 2013

How are you importing the page structure?

@jurriaan
Copy link
Contributor

I just loop the old CMS page structure and create the Pages and PageParts manually.

@jurriaan
Copy link
Contributor

Just updated to refinery edge, still having the same bug.

@euomarcelo
Copy link

For anyone that may still have this problem, it's worth checking this file:

pathtoyourapp/config/initializers/refinery/i18n.rb

You may have forgotten to set config.frontend_locales with the languages/locales that your site supports, in my case:

config.frontend_locales = [:en, :'pt-BR']
config.locales = {:en=>"English", :"pt-BR"=>"Português brasileiro"}

After doing so, don't forget to restart the server =)

This worked for me (Refinery 2.1.1), no pages overrides needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests